将值设置为模拟对象但获取null

时间:2015-12-10 14:58:31

标签: java unit-testing mocking mockito

我有一个简单的类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特定的问题还是模仿对象无法设置值的约定?这是为什么?下面用模拟对象发生了什么?

6 个答案:

答案 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