将值设置为模拟对象但得到 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 的特定问题还是模拟对象不能设置值的约定?这是为什么?模拟对象下面发生了什么?
是的 - Foo
的 actual 代码无关紧要,因为你在嘲笑它......而且 Mockito 不知道这意味着是 setName
和 getName
之间的关系。当调用 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
我有一个简单的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 的特定问题还是模拟对象不能设置值的约定?这是为什么?模拟对象下面发生了什么?
是的 - Foo
的 actual 代码无关紧要,因为你在嘲笑它......而且 Mockito 不知道这意味着是 setName
和 getName
之间的关系。当调用 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