我的用例的代码如下:
我的班级:
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
public class MyClass {
public String getString() {
// object need mocking
ObjectMapper mapper = new ObjectMapper()
try {
// method need mocking
return mapper.writeValueAsString(List.of("1", "2"));
}
catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
}
}
测试代码:
@Test
public void test_get_string() throws Exception {
ObjectMapper mapper = Mockito.mock(ObjectMapper.class);
Mockito.when(mapper.writeValueAsString(Mockito.anyList()))
.thenThrow(JsonProcessingException.class);
Assertions.assertThrows(RuntimeException.class, () -> {
new MyClass().getString();
});
// -> failed
// Expected RuntimeException but nothing was thrown
}
我想模拟
ObjectMapper
并使其在 JsonProcessingException
方法调用上抛出 writeValueAsString
,但测试一直失败,就好像它根本不使用我的模拟映射器一样。但是如果我将映射器设为 MyClass
的属性并模拟它,那么测试就会通过。
public class MyClass {
// make mapper a property
private ObjectMapper mapper;
public MyClass(ObjectMapper mapper) {
this.mapper = mapper;
}
public String getString() {
try {
return mapper.writeValueAsString(List.of("1", "2"));
}
catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
}
}
@Test
public void test_get_string() throws Exception {
ObjectMapper mapper = Mockito.mock(ObjectMapper.class);
Mockito.when(mapper.writeValueAsString(Mockito.anyList()))
.thenThrow(JsonProcessingException.class);
Assertions.assertThrows(RuntimeException.class, () -> {
// pass mapper on creating object
new MyClass(mapper).getString();
}); // -> success
}
如果我不想让映射器成为我的类的属性,我应该如何正确地模拟它?
您无法使用 Mockito 模拟在方法中声明的局部变量。您可以将
ObjectMapper
设为您班级 MyClass
的属性。但如果您不想这样做,另一个选择是在您的 MyClass
中添加一个受保护的方法,该方法返回 ObjectMapper
的实例
public class MyClass {
public String getString() {
// object need mocking
ObjectMapper mapper = createObjectMapper()
try {
// method need mocking
return mapper.writeValueAsString(List.of("1", "2"));
}
catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
}
protected ObjectMapper createObjectMapper() {
return new ObjectMapper();
}
}
然后在您的测试用例中,您可以
spy
您的类并存根这个新方法以返回模拟的ObjectMapper
,如下所示:
@Test
public void test_get_string() throws Exception {
ObjectMapper mapper = Mockito.mock(ObjectMapper.class);
Mockito.when(mapper.writeValueAsString(Mockito.anyList()))
.thenThrow(JsonProcessingException.class);
MyClass myClass = Mockito.spy(new MyClass ());
doReturn(mapper).when(myClass).createObjectMapper();
Assertions.assertThrows(RuntimeException.class, () -> {
myClass.getString();
});
}