我正在尝试使用Mockito编写Java单元测试,但是无法使匹配器工作。
我想测试以下类
定制服务.java
public class CustomService {
private final ApplicationProperties props;
public CustomService(ApplicationProperties props){
this.props = props;
}
private final ObjectMapper mapper = new ObjectMapper();
public void method(JsonNode message) throws CustomException {
try {
List<String> actions = mapper.readValue(message.get("actions").toString(), mapper.getTypeFactory().constructCollectionType(List.class, String.class));
System.out.println(actions);
} catch (IOException ex){
throw new CustomException(ex);
}
}
}
我有一个自定义异常类
自定义例外.java
@ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
public class CustomException extends Exception {
public CustomException(Throwable cause) {
super(cause);
}
}
我想测试是否抛出自定义异常。 我正在使用莫克托。 我已经尝试了下面的方法,但给定的语句似乎没有在方法中获取(readValue(代码行
定制服务测试.java
public class CustomServiceTest {
private final ApplicationProperties props = mock(ApplicationProperties.class);
private final CustomService customService = new CustomService(props);
private static final ObjectMapper objectMapper = new ObjectMapper();
@Test
public void CustomExceptionIsThrown() throws Exception {
ObjectMapper mapper = mock(ObjectMapper.class);
given(mapper.readValue(anyString(), any(TypeReference.class))).willThrow(new IOException("This is a test"));
String json = "{"actions":["ac1","ac2","ac3","ac4"]}";
JsonNode d = objectMapper.readTree(json);
assertThrows(CustomException.class, () ->
customService.method(d));
}
}
运行测试时出现以下错误
Expected exception.CustomException to be thrown, but nothing was thrown..
帮助将不胜感激。
我也遇到了同样的问题,我发现虽然我像"when(objectMapper.readValue(anyString((, any(TypeReference.class(((.thenReturn(xxxx(;"但是当我调用测试时,readValue(xx,xx( 的第一个参数为null,它应该是一个字符串对象。因此,您可能需要再次检查 readValue 方法输入参数。希望它会有所帮助。
您的示例代码仍然存在一些问题。
-
您没有将
ObjectMapper
模拟注入CustomService
课。 -
由于您正在测试的类现在具有 args 构造函数,因此您将无法将模拟注入到测试中。您需要调整构造函数以从外部传递
ObjectMapper
或依靠Reflections
手动放置模拟。
一般建议是将ObjectMapper
作为论据传递给解释者。这样做,您无需更改字段mapper
上的final
。
private final ApplicationProperties props;
private final ObjectMapper mapper;
public CustomService(ApplicationProperties props, ObjectMapper mapper){
this.props = props;
this.mapper = mapper;
}
您仍未定义调用
getTypeFactory()
方法时模拟的行为。此时你应该得到一个NullPointerException
(如果你的代码实际上使用了那个模拟(。
在下面的示例中,我使用RETURNS_DEEP_STUBS
选项替换了此定义, 这导致mapper.getTypeFactory().constructCollectionType(List.class, String.class)
返回CollectionType
的模拟。不需要带有
TypeReference
的模拟定义,因为它与调用readValue
方法时使用的方法参数不匹配。相反,您将不得不使用CollectionType
.由于测试的方法
void
因此必须改用willThrow(...).given(...)
语法。
这里有一个工作测试的例子:
(仅适用于具有no-args构造函数的CustomService
类(
@ExtendWith(MockitoExtension.class)
public class JacksonTest {
static class CustomException extends Exception {
public CustomException(IOException ex) {
super(ex);
}
}
static class CustomService {
private ObjectMapper mapper = new ObjectMapper();
public void method(String c) throws CustomException {
try {
mapper.readValue(c, mapper.getTypeFactory().constructCollectionType(List.class, String.class));
} catch (IOException ex){
throw new CustomException(ex);
}
}
}
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
ObjectMapper mapper;
@InjectMocks
CustomService customService;
@Test
public void testCustomExceptionIsThrown() throws Exception {
BDDMockito.willThrow(new IOException("This is a test")).given(mapper).readValue(ArgumentMatchers.anyString(), ArgumentMatchers.any(CollectionType.class));
Assertions.assertThrows(CustomException.class, () -> customService.method("x"));
}
}
依赖:
testCompile "org.junit.jupiter:junit-jupiter-api:5.5.2"
testCompile "org.junit.jupiter:junit-jupiter-engine:5.5.2"
testCompile "org.mockito:mockito-core:3.0.0"
testCompile "org.mockito:mockito-junit-jupiter:3.0.0"
compile "com.fasterxml.jackson.core:jackson-databind:2.9.9"