我想编写一个单元测试来测试JSONProcessingException。该例外可能会在线上发生:mapper.writeValueasString()。
public void myMethod(Args...) {
try {
ObjectMapper mapper = new ObjectMapper();
mapper.configure(SerializationFeature.INDENT_OUTPUT, true);
Document.parse(mapper.writeValueAsString(testObject)));
}
} catch (JsonProcessingException e) {
log.error("Error parsing the object to json string. ", e);
}
}
这是我的单位测试:
public class Test {
@Mock
private ObjectMapper mapper;
@InjectMocks
ClassUnderTest sut;
@Test
public void testJsonProcessingException() throws JsonProcessingException {
when(mapper.writeValueAsString(Mockito.any())).thenThrow(new JsonProcessingException("Error parsing the object to json string. "){
private static final long serialVersionUID = 1L;});
sut.myMethod(args...);
}
}
问题是我所模拟的映射器将不会被使用(我会不会获得不必要的oblito stubbings失败),因为映射器在方法内再次初始化。我如何使用Mockito进行单元测试?
mapper
不是测试实例的字段/依赖性。
它是该方法中创建的局部变量:
public void myMethod() {
try {
ObjectMapper mapper = new ObjectMapper();
...
}
所以,@InjectMocks
将是无助的。
我可以提出两个替代方案:
1)您可以通过更改方法的签名来传递mapper
作为参数:
public void myMethod(ObjectMapper mapper) {
...
}
这样,您可以将模拟的ObjectMapper
作为测试方法的参数传递。
如果经常调用此方法,则通过锅炉板参数可能很烦人,并且使代码不那么可读。
2)另一种方法是通过正在测试的类的构造函数设置ObjectMapper
的方法。
public class ClassUnderTest{
private ObjectMapper objectMapper;
...
public ClassUnderTest(ObjectMapper objectMapper){
this.objectMapper = objectMapper;
}
...
}
使用objectMapper测试方法并抛出自定义(包装JSONProcessingException),我们需要模拟对象mapper并告诉它进行异常。
这是一个可以解析jsonnode并进行自定义异常的方法:
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor
public class MyService {
private final ObjectMapper objectMapper;
public Boolean processSomething(JsonNode jsonNode) {
Simple simple;
try {
simple = objectMapper.readValue(jsonNode.toString(), Simple.class);
} catch (JsonProcessingException e) {
throw new CustomServerException(e.getMessage(), e);
}
return true;
}
}
测试此方法:
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.my.path.MyService;
import org.assertj.core.api.Assertions;
import org.mockito.Mockito;
import org.testng.annotations.Test;
public class TestMyService {
// To test the method for the CustomServerException,
// we need to mock the ObjectMapper to throw the JsonProcessingException:
@Test
void testProcessSomething_JsonProcessingException() {
// using a mock ObjectMapper to force a JsonProcessingException to be thrown
ObjectMapper mockMapper = Mockito.mock(ObjectMapper.class);
MyService serviceWithMockMapper = new MyService(mockMapper);
CustomServerException thrown = assertThrows(CustomServerException.class, () -> {
when(mockMapper.readValue(jsonNode.toString(), Simple.class)).thenThrow(JsonProcessingException.class);
serviceWithMockMapper.processSomething(jsonNode);
});
Assertions.assertNotNull(thrown.getMessage());
}
}