我有一个简单的类Foo
被嘲笑:
public class Foo {
private String name;
public Foo() {
}
public Foo(String name) {
this.name = name;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
在我的单元测试代码中,我使用Mockito来模拟它。
Foo mockedFoo = Mockito.mock(Foo.class);
mockedFoo.setName("test");
// name is null
String name = mockedFoo.getName();
我在模拟对象中设置name
,但是当我调用getter获取名称时,它返回 null 。
它是Mockito特定的问题还是模仿对象无法设置值的约定?这是为什么?下面用模拟对象发生了什么?
答案 0 :(得分:21)
是的 - Foo
的实际代码并不重要,因为你在嘲笑它......而且Mockito不知道那里的意思是{ {1}}和setName
。它不会假设它应该将参数存储到getName
并在调用setName
时返回它...它可以这样做,但它不是那么远我知道。 Mockito提供的模拟只允许您指定在调用方法时会发生什么,并检查稍后调用的 。您可以模拟对getName
的调用并指定它应返回的内容,而不是调用setName
...
...或者你可以直接使用getName()
而不是嘲笑它。不要以为你必须在测试中模拟所有。只是嘲笑(或伪造)当你使用真正的类时很尴尬的东西,例如因为它使用文件系统或网络。
答案 1 :(得分:8)
默认情况下,mockito对模拟对象中的任何方法都没有行为。
你应该这样做:
Foo mockedFoo = Mockito.mock(Foo.class);
when(mockedFoo.getName()).thenReturn("someName");
String name = mockedFoo.getName();
编辑:正如Jon Skeet所提到的,你不应该模仿那些只能以正常方式进行测试的东西。
答案 2 :(得分:2)
我认为,更好地理解 Mockito 对您的参数类所做的事情以及它通过引用源代码返回的对象类型Mockito Source
一般的理解是,模拟对象是一个伪对象(与提供给mock()
方法的参数类型相同),没有真正的方法实现。基本上,在现实生活中没有任何事情发生在模拟对象上的方法调用 - 这就是创建一个模拟对象的目的(我们不希望称之为真正的方法),不是吗?
我们模拟DAO层,LDAP层或其他服务依赖项,因为我们不想调用对实际DB或服务的调用。 如果我们想要真正的调用,我们就不会创建模拟对象。
在调用mockedFoo.setName("test");
OR mockedFoo.getName();
之后理解发生了某些事情是不正确的 - 在对模拟对象调用方法之后没有任何反应,这是它正在实现的模拟对象的目的。
答案 3 :(得分:0)
要解决有关知道是否在代码中使用指定值调用setName()方法的问题,请使用Mockito验证方法。
例如:
verify(mockedFoo, times(1)).setName("test");
将验证带有String参数“ test”的mockedFoo.setName()方法在被测代码中仅被调用一次。
答案 4 :(得分:0)
要使用这种方法。我已经为EasyMock撰写过文章,但与Mockito一样,它也可以相同地使用。
String nameMock = createNiceMock(String.class);
Foo MockedFoo = new Foo();
Foo.setName(nameMock);
EasyMock.expect(Foo.getName()).andReturn(nameMock);
答案 5 :(得分:0)
您需要在模拟对象上调用真实方法。使用@Spy