将值设置为模拟对象,但得到null



我有一个简单的类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特有的问题,还是被嘲笑对象不能设置值的约定?为什么?被嘲笑的物体下面发生了什么?

是的,Foo实际代码无关紧要,因为你在嘲笑它……Mockito不知道setNamegetName之间有关系。它不认为它应该将参数存储到setName,并在调用getName时返回。。。它可以做到这一点,但据我所知,它还没有做到。Mockito提供的mock只允许您指定对其调用方法时会发生什么,并检查稍后调用了什么。您可以模拟对getName()的调用,并指定它应该返回什么,而不是调用setName。。。

或者你可以直接使用Foo而不是嘲笑它。不要认为你必须在测试中嘲笑所有。在使用真实类时,只需模拟(或伪造)一些尴尬的事情,例如,因为它使用了文件系统或网络。

默认情况下,mockito在模拟对象中的任何方法上都没有行为。

你应该这样做:

Foo mockedFoo = Mockito.mock(Foo.class);
when(mockedFoo.getName()).thenReturn("someName");
String name = mockedFoo.getName();

编辑:正如Jon Skeet所提到的,你不应该嘲笑那些可以正常测试的东西。

我认为,通过引用源代码Mockito source ,更好地理解Mockito对参数类做了什么,以及它返回了什么样的对象

一般的理解是,模拟对象是一个伪对象(与提供给mock()方法的参数类型相同),没有真正的方法实现。所以基本上,在现实生活中,方法调用模拟对象不会发生任何事情——这正是创建模拟对象的目的(我们不希望调用真正的方法),不是吗?

我们模拟DAO层、LDAP层或其他服务依赖关系,因为我们不想调用对实际DB或服务的调用如果我们想要真正的调用发生,我们就不会创建模拟对象

理解在调用mockedFoo.setName("test");mockedFoo.getName();之后发生了真实的事情是不正确的——在对模拟对象调用方法之后什么都不会发生,这就是它正在实现的模拟对象的目的。

要解决您知道代码中是否使用指定值调用了setName()方法的问题,请使用Mockito验证方法。

例如:

verify(mockedFoo, times(1)).setName("test");

将验证具有String参数"test"的mockedFoo.setName()方法在测试中的代码中是否只调用过一次。

您需要在模拟对象上调用真正的方法。使用@Spy

在某种程度上使用这种方法。我为EasyMock写过文章,但有了Mockito,它也可以同样使用。

String nameMock = createNiceMock(String.class);
Foo MockedFoo = new Foo();
Foo.setName(nameMock);
EasyMock.expect(Foo.getName()).andReturn(nameMock);

相关内容

  • 没有找到相关文章

最新更新