为啥可以毫无问题地测试 Spock 中的私有方法/字段?

Posted

技术标签:

【中文标题】为啥可以毫无问题地测试 Spock 中的私有方法/字段?【英文标题】:Why can test private methods/fields in Spock without problems?为什么可以毫无问题地测试 Spock 中的私有方法/字段? 【发布时间】:2014-12-15 09:30:06 【问题描述】:
package com.example.dev;
public class AClass 
 private Integer a =10;
...//other code

当我尝试在我的 Spock 方法中访问 a 时:

package com.example.dev;
def 'test a'() 
 AClass aClassVar = new AClass()
 aClassVar.a = new Integer(100);
...//other testing stuff

它工作正常。为什么会发生这种情况? Spock 是否使用反射来访问私有字段?还是我的封装写得不好?

【问题讨论】:

这能回答你的问题吗? Private method in groovy is not private 【参考方案1】:

Spock 没有罪,它本身就很时髦,请参阅:Private method in groovy is not private。

虽然可以引用类的私有成员,但这绝对不是一个好习惯。

【讨论】:

为什么这不是一个好习惯?同样在未来,你认为 groovy 会取消对此的支持吗(访问私有方法)? 类的内部结构?如果我们可以测试私有方法,我们当然也可以测试它们的合约(比如它们基于输入返回的内容等,这要归功于 groovy)。如果将来返回类型等发生变化,那么测试当然会失败。即使对于公共方法也是如此。我仍然不明白这是一个不好的做法?也许你的意思是说通过测试私有方法(使用 groovy 的魔法语法等),它可能不安全? 难道我们不会仍然存根底层服务并且只测试 getData 的合同吗?如果合同发生变化,那么它是重做测试的有效方案。我的意思是,即使应该是私有的方法(getData)最终是公开的或者使用 groovy 魔法进行测试,我们仍然会遵循测试约定并且只测试它的合同,对吗?仅仅因为它是一个私有方法,并不意味着我们会打破单元测试约定。对不起,如果我误解了。谢谢回复。 :) 如果 getData 确实应该是公开的,而我们按照你说的做了,那么我们的测试约定很糟糕。在进行单元测试时,为什么我们不存根基于 Http 的内部或方法所需的其他依赖项?在这个单元测试期间,我们不应该只测试 getData 假设所有依赖项都按照他们的合同工作(我的意思是 http 方法)。 @theprogrammer,也请参考 softwareengineering.stackexchange.com/a/100966/177830 和 softwareengineering.stackexchange.com/a/375866/177830 及其 cmets 了解为什么不应该对私有方法进行单元测试。【参考方案2】:

据我了解

aClassVar.a = new Integer(100)

在 Groovy / Spock 中只是语法糖

aClassVar.setA(new Integer(100));

在 Java 中。在某些情况下,我尝试这样做,但没有二传手,Spock 抱怨道。

至于为什么我们创建私有属性,然后给它们设置器,那是另一个讨论。

【讨论】:

以上是关于为啥可以毫无问题地测试 Spock 中的私有方法/字段?的主要内容,如果未能解决你的问题,请参考以下文章

如何使IDEA识别Spock的with()方法?

吃透单元测试一,Spock单元测试框架的应用与实践

大量的 spock 测试导致 eclipse 中的编译时间很长

在 Spock 中的项目列表上断言

如何在 Grails 单元测试中使用 Spock 模拟 passwordEncoder

Groovy/Spock 测试导论