我需要为调用服务的rest控制器端点编写单元测试,该服务调用RestTemplate exchange()
@RestController
public class MyController {
@Autowired
Myservice myservice;
@GetMapping("todo")
public ResponseEntity<String> getTodo() {
String todoJson = myservice.getTodo();
return ResponseEntity.ok(todoJson);
}
}
这是我的服务类
@Service
public class Myservice {
public String getTodo() {
ResponseEntity<Todo> response = restTemplate.exchange("https://jsonplaceholder.typicode.com/todos/1", HttpMethod.GET, null, Todo.class);
Todo todo = response.getBody();
return objectMapper.writeValueAsString(todo);
}
}
和测试用例
@ExtendWith(SpringExtension.class)
class MyControllerTestJunit5 {
private MockMvc mockMvc;
@Mock
private RestTemplate restTemplate;
@InjectMocks
MyController myController;
@Mock
Myservice myservice;
@BeforeEach
void setUp() {
mockMvc = MockMvcBuilders.standaloneSetup(myController).build();
}
@Test
public void mockResttemplate() throws Exception {
Todo todosample = new Todo(5,6,"myfield", true);
ResponseEntity<Todo> responseEntity = ResponseEntity.ok(todosample);
when(restTemplate.exchange(
ArgumentMatchers.anyString(),
any(HttpMethod.class),
ArgumentMatchers.any(),
ArgumentMatchers.eq(Todo.class)))
.thenReturn(responseEntity);
MvcResult result = mockMvc.perform(MockMvcRequestBuilders.get("/todo"))
.andExpect(status().isOk())
.andReturn();
String myresult = result.getResponse().getContentAsString();
System.out.println("response: " + myresult);
}
在最后打印响应显示响应是空的。2我怎样才能让它工作呢?
1条答案
按热度按时间zsbz8rwp1#
我假设您希望获得
todosample
对象的JSON表示。测试中的问题是您通过使用@Mock
注解Myservice
来模拟Myservice
。这个模拟的服务被MyController
使用,因为它是使用@InjectMocks
注解的。因此,当您调用/todo
端点时,控制器调用myservice.getTodo()
,它返回null
,因为Myservice
模拟没有被配置为返回任何其他内容。在此之后,null
值将被传播到ResponseEntity
主体,该主体将在测试中具体化为空的OK响应。我相信,对于这种测试,更好的方法是模拟
Myservice
并对其进行正确的配置。第一部分已经完成了,正如我提到的。配置很简单。您只需将restTemplate.exchange
调用配置替换为myservice.getTodo()
调用配置。类似于以下内容应该可以工作:然后,您可以对
Myservice
进行单独的测试,其中您必须模拟restTemplate.exchange
调用。当然,从技术上讲,您仍然可以在
MyController
测试中模拟restTemplate
,但您必须确保示例化真实的Myservice
,而不是模拟的版本。然而,在这种情况下,您将向MyController
类公开Myservice
的实现细节,这与MVC模式有点矛盾。