我一直在进行一些单元测试,并且只是进入整个主题。
我偶然发现了以下情况,假设我有一个这样的课程:
class A{
public B mehtod_1(B b){
b = method_2(b);
b = method_3(b);
b += 1;
return b;
}
public B method_2(B b){
// do something to B without external dependency
return B;
}
public B method_3(B b){
// do something else to B without external dependency
return B;
}
}
我可以毫无问题地为method_2
和method_3
编写测试,通过以不同方式配置B并在调用后断言B上的预期转换来执行不同的测试,这些方法是原子的。
所以我的问题是:
如果我以原子方式测试method_1
,我将不得不模拟对method_2
和method_3
的调用,因为如果我实际上调用这些方法,我就不会测试{{ 1}}在一个原子庄园里。
在后一种情况下method_1
被打破,method_2
和method_1
的测试会中断,这会产生误导。如果我在method_2
测试中模拟method_2
调用,则只有method_1
测试会失败,从而更清楚地指示错误的位置(即业务逻辑中的某处)如果所有其他调用的方法按预期工作,则为method_2
。
我是否正确理解了这个概念?
另一方面,如果两个测试都失败,那是正确的,因为在现实世界中,method_1
无法在method_1
工作的情况下工作。
我的直觉是说测试的原子性是所期望的,这意味着第一个解决方案,其中method_2
有一个测试,method_1
和method_2
的每个可能结果(静态模拟) )。
是否有"正确" /普通/最佳做法?
答案 0 :(得分:1)
立即回答:如果我们在这里谈论Java; 部分嘲笑对你很感兴趣,你可以考虑使用Mockito的spy概念。
但除此之外:你的单元测试错误了。你所谓的 atomicity ;我打电话给担心实施细节。但它并不重要"究竟是什么"那个"测试方法"实际上。您想测试 ,而不是如何。
含义:如果该方法必须调用其他方法(在单元测试环境中正常工作;不进行模拟);那么就没有必要考虑嘲笑它们了!
您会看到:您关心每种方法的合同。那个合约是你要测试的:给出这些输入参数,我期待那个结果/副作用/异常......
尽管如此,您有多个公共方法;并且他们以某种方式相互依赖可能表示设计问题(如:它们是否全部公开有意义;是否有一些隐藏在界面中的抽象,你应该更好地表达在其他方面?)。但这只能在真实代码的情况下决定;真实的背景。