使用mockito模拟方法是否确保永远不会调用mocked方法?我有Main类,其中包含一些我想编写单元测试的代码,我有一个单元测试类MainTest,它包含Main类的单元测试。
例如:
来源类:
package abc;
public class Main {
public int check1() {
int num = 10;
num = modify(num);
return num;
}
public int modify(int num) {
if (num % 10 == 0) return num / 10;
return -1;
}
}
Junit测试(使用mockito)
package abc;
import junit.framework.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import org.mockito.Mockito;
public class MainTest {
private static Main main;
@BeforeClass
public static void setUp() {
main = Mockito.mock(Main.class);
Mockito.when(main.modify(10)).thenReturn(5);
}
@Test
public void testCheck1() {
Test1 main1 = new Main();
int num = main.check1();
Assert.assertEquals(5, num);
}
}
此测试失败。为什么呢?
答案 0 :(得分:8)
<强> EDITED 强>
因为您没有为check1()
提供行为。 所有方法都被模拟,因此,如果没有提供行为,check1()
将返回int的返回类型的默认值,即0。此外,check1()
因为它被模拟甚至没有打电话给modify()
。
如果您正在尝试测试一个类,那么您永远不会模拟测试类。在极少数情况下,您可能需要Spy正在测试的课程。相反,你只是模仿合作者。
我猜你的例子是一个人为的(我希望)。但是,如果您正在编写和测试一个您认为要修改某个内部方法行为的类,我会看到两个可能的概率:
check1()
会对其传递给modify()
的值进行硬编码,这就是您尝试模拟modify()
的原因。如果该值是check1()
的参数或类Main
中的可设置字段,则根本不需要使用模拟。答案 1 :(得分:4)
测试问题是,您不使用新创建的main1对象。
如果你想改变被测系统(SUT)的行为,你通常会做这样的事情:
@Test
public void testCheck1() {
Test1 main1 = new Main(){
public int modify(int num) {
return 5; // hard coded return value
}
};
int num = main1.check1();
Assert.assertEquals(5, num);
}
这将创建Main的子类,其中包含modify-method的新实现。 这是替换SUT中难以测试的方法的重要技术。您通常会使用它来避免昂贵的远程呼叫或类似的。
当然可以像这样使用Mockito间谍:
@Test
public void testCheck1() {
Test1 main1 = spy(new Main());
stub(main1.modify(10)).toReturn(5);
int num = main1.check1();
Assert.assertEquals(5, num);
}
答案 2 :(得分:0)
虽然我迟到了,但对某些人来说可能有用。刚刚添加到@VivaceVivo答案:使用间谍时请考虑doReturn | Answer | Throw()系列方法进行存根。有时,使用(对象)咒语间谍是不可能或不切实际的。更多信息here