aqu*_*ode 9 java unit-testing mockito
也许我在搜索中完全不知所措,但我找不到任何与如何为Java类/方法编写单元测试相关的文档或讨论,而Java类/方法又调用其他非私有方法.看起来,Mockito认为,如果必须使用间谍来测试一种需要模拟内部方法调用的方法,那么设计可能存在问题(不是真正的OO).我不确定这是永远的.但是使用间谍似乎是实现这一目标的唯一方法.例如,为什么你不能有一个"包装"样式方法,而这种方法依赖于原始功能的其他方法,但另外提供功能,错误处理,日志记录或依赖于其他方法的结果的不同分支等?
所以我的问题是双重的:
这可能是一个困难的要求,但我更愿意那些决定回答不仅重新发布Mockito措辞和/或对间谍的立场,因为我已经意识到这种方法和意识形态.另外,我也使用过Powermockito.对我来说,问题在于Mockito开发了这个框架,必须创建额外的解决方案来支持这种需求.所以我想我想要回答的问题是,如果间谍是"坏",并且Powermockito不可用,那么应该如何对一个调用其他非私有方法的方法进行单元测试呢?
小智 7
是否设计不良并且实现了具有内部调用其他方法的方法的代码?
并不是的.但是我要说的是,在这种情况下,应该测试调用其他方法的方法,就像其他尚未单独测试的方法一样.也就是说,它可以保护您免受公共方法在没有注意到的情况下停止调用其他方法的情况.
是的,它(通常)有很多测试代码.我相信这就是重点:编写测试的痛苦是一个很好的线索,你可能想要考虑将这些子方法提取到一个单独的类中.
如果我可以忍受那些测试,那么我认为子方法还没有被提取出来.
如果选择Mockito作为他们的模拟框架,那么为这种方法编写单元测试的最佳实践和/或方法是什么(假设它本身是一个好主意)?
我会做那样的事情:
public class Blah {
public int publicMethod() {
return innerMethod();
}
int innerMethod() {
return 0;
}
}
public class BlahTest {
@Test
public void blah() throws Exception {
Blah spy = spy(new Blah());
doReturn(1).when(spy).innerMethod();
assertThat(spy.publicMethod()).isEqualTo(1);
}
}
Run Code Online (Sandbox Code Playgroud)
如果您确实需要(或想要)避免再次调用较低级别的方法,您可以将它们存根而不是模拟它们。例如,如果方法 A 调用 B 和 C,您可以这样做:
MyClass classUnderTest = new MyClass() {
@Override
public boolean B() {return true;}
@Override
public int C() {return 0;}
};
doOtherCommonSetUp(classUnderTest);
String result = classUnderTest.A("whatever");
assertEquals("whatIWant", result);
Run Code Online (Sandbox Code Playgroud)
我在遗留代码中经常使用这种方法,其中大量的重构很容易导致软件版本的造船者疾病:将难以测试的东西隔离到一个小方法中,然后将其存根。
但是,如果被调用的方法相当无害并且不需要模拟,我只是让它们再次被调用,而不用担心我覆盖了它们中的每条路径。