我是Mockito的新手,请帮助理解基本知识。
根据我的说法,当mocked.add(6,7)
被调用时,上面的代码应该打印5,但add()
方法没有被调用,代码打印0。为什么?有这个代码的解决方案吗?
import org.mockito.Mockito;
import static org.mockito.Mockito.*;
class Calc{
int add(int a,int b){
System.out.println("add method called");
return a+b;
}
}
class MockTest{
public static void main(String[] args) {
Calc mocked=mock(Calc.class);
when(mocked.add(2,3)).thenReturn(5);
System.out.println(mocked.add(6,7));
}
}
为了得到5的结果,您必须像设置when时一样传递精确的params。。然后否则mockito将返回一个"默认"值(对于integer:为0
mock默认返回什么值?
为了透明和不引人注目,所有Mockito模仿默认值返回"nice"值。例如:零、假、空集合或null。请参阅javadocs中关于存根的内容,以了解详细信息默认情况下返回哪些值。
如果您想为任何整数返回5,请使用:
when(mocked.add(Mockito.any(Integer.class),Mockito.any(Integer.class))).thenReturn(5);
"mock"只是一个模拟"真实"对象行为的空虚拟对象。如果定义像when(mocked.add(2,3)).thenReturn(5);
这样的行为,那么当mock接收到这些精确值时,您会特别告诉它该做什么。
此时mocked.add(6,7)
将返回0
,因为您尚未为这些值定义其行为,因此使用默认值。因此,如果你想涵盖所有可能的输入,你可以使用@MaciejKowalski发布的解决方案,并使用像Mockito.any(Integer.class)
这样的通用匹配器。
尽管如此,我仍然认为如何正确处理mock还不清楚。Mock是一种向测试中的系统提供外部依赖关系的方式,而无需设置整个依赖关系树。该类中的实际方法通常不会被调用。这就是when(mocked.add(2,3)).thenReturn(5);
的含义。它告诉mock像真正的依赖一样表现,而实际上没有它。
例如:
public class TestClass {
private ExternalDependency dep;
public void setDep(ExternalDependency dep) {
this.dep = dep;
}
public int calculate() {
return 5 + dep.doStuff();
}
}
public class ExternalDependency {
public int doStuff() {
return 3;
}
}
现在,在你的测试代码中,你可以使用这样的模拟:
@Test
public void should_use_external_dependency() {
// Aquire a mocked object of the class
ExternalDependency mockedDep = Mockito.mock(ExternalDependency.class);
// Define its behaviour
Mockito.when(mockedDep.doStuff()).thenReturn(20);
TestClass sut = new TestClass();
sut.setDep(mockedDep);
// should return 25, since we've defined the mocks behaviour to return 20
Assert.assertEquals(25, sut.calculate());
}
如果调用了sut.calculate()
,则不应真正调用ExternalDependency
中的方法,而是将其委托给模拟的存根对象。但是,如果您想调用real类的real方法,您可以使用Spy代替Mockito.spy(ExternalDependency.class)
,也可以使用when(mockedDep.doStuff()).thenCallRealMethod();