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

Set value to mocked object but get null

我有一个简单的classFoo要嘲笑:

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 来获取它的名称时 returns null

这是 Mockito 的特定问题还是模拟对象不能设置值的约定?这是为什么?模拟对象下面发生了什么?

是的 - Fooactual 代码无关紧要,因为你在嘲笑它......而且 Mockito 不知道这意味着是 setNamegetName 之间的关系。当调用 getName 时,它不假定它应该将参数存储到 setName 和 return 它......它 可以 这样做,但据我所知并非如此。 Mockito 提供的 mock 只允许您指定在其上调用方法时发生的情况,并检查 was 稍后调用的内容。除了调用 setName,您还可以模拟对 getName() 的调用并指定它应该 return...

... 或者您可以直接使用 Foo 而不是模拟它。不要认为您必须在测试中模拟 一切。只是模拟(或伪造)当你使用真实 class 时尴尬的东西,例如因为它使用了文件系统或网络。

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

你应该这样做:

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

编辑:正如 Jon Skeet 所提到的,您不需要模拟那些只能以正常方式测试的东西。

我认为,最好通过参考源代码来理解 Mockito 对您的论点 class 做了什么以及它 returns 是什么对象, Mockito Source

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

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

关于在调用 mockedFoo.setName("test");mockedFoo.getName(); 后发生真实情况的理解是不正确的 - 在对模拟对象调用方法后没有任何反应,这就是模拟对象的目的充实。

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

例如:

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

将验证带有字符串参数 "test" 的 mockedFoo.setName() 方法在被测代码中被调用了一次。

有点用这种方法。我已经为 EasyMock 编写了,但是对于 Mockito,它也可以同样使用。

String nameMock = createNiceMock(String.class);
Foo MockedFoo = new Foo();
Foo.setName(nameMock);

EasyMock.expect(Foo.getName()).andReturn(nameMock);

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