java - 用于 TypeReference 的 Mockito 匹配器
问题描述
我正在尝试使用 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);
}
}
}
我有一个 CustomException 类
自定义异常.java
@ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
public class CustomException extends Exception {
public CustomException(Throwable cause) {
super(cause);
}
}
我想测试是否抛出了 CustomException。我正在使用 Mockito。我已经尝试过以下方法,但给定的语句似乎没有在方法中获取 (readValue) 行代码
CustomServiceTest.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..
帮助将不胜感激。
解决方案
您的示例代码仍然存在一些问题。
您没有将 Mock of
ObjectMapper
注入您的CustomService
班级。由于您的测试类现在有一个 args 构造函数,您将无法将模拟注入您的测试。您将需要调整构造函数以
ObjectMapper
从外部传递或依靠Reflections
手动放置模拟。
一般的建议是将ObjectMapper
as 参数传递给构造函数。这样做,您将不需要更改final
on the field mapper
。
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(...)
语法。
这是一个工作测试的示例:(
仅适用于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"
推荐阅读
- javascript - 仅当另一个 div 有内容时才显示一个 div (React)
- ruby-on-rails - 没有路线匹配 {:action=>"create", :controller=>"reviews", :id=>"2", :user_id=>#
我正在处理 user_profile_reviews 并且卡住了。我现在有 3 个模型,而且我知道,为个人资料制作单独的模型并不是一个好主意,
- bash - Bash 脚本 [macOS Sierra 终端] 为给定的每个子目录创建一个 .dmg
- java - 将字符串分离为数组
- php - WordPress:在用户个人资料页面中保存复选框并在公共页面中检索
- tensorflow - 创建像 relu6 这样的自定义非线性
- angular - 如何将 TradingView 嵌入到 Angular 8 项目中?
- c++ - 转换 std::variant到 std::variant
- delphi - 如何检测动画 GIF?
- reactjs - 将 firebase 作为参数添加到 thunk 时,Object(...) 不是函数