【发布时间】:2021-09-23 21:15:23
【问题描述】:
当模拟的restTemplate 调用时,我在第二个测试中看到的行为是 NullPointerException。这指出了重置模拟的问题。令我惊讶的是修复(使两个测试都通过)。
修改代码
@MockBean private RestTemplate restTemplate;
到
@MockBean(reset = MockReset.NONE) private RestTemplate restTemplate;
解决了这个问题。这里有几个问题:
- 为什么 MockReset.RESET 的默认 @MockBean 行为不起作用?
- 我设置测试的方式是否有问题,导致默认 MockReset.RESET 失败?
- 测试配置类有问题吗?
希望我已经提供了足够的上下文来回答这个问题。
我创建了一个简化的示例来说明我所看到的: 测试配置:
@Profile("test")
@Configuration
public class TestConfiguration {
@Bean
@Primary
public ObjectNode getWeatherService(RestTemplate restTemplate) {
return new WeatherServiceImpl(restTemplate);
}
}
测试:
@SpringBootTest
@ActiveProfiles("test")
@AutoConfigureMockMvc
class SamTest {
@Autowired private MockMvc mockMvc;
@MockBean private RestTemplate restTemplate;
/*
Works:
@MockBean(reset = MockReset.NONE) private RestTemplate restTemplate;
Fails:
@MockBean(reset = MockReset.BEFORE) private RestTemplate restTemplate;
@MockBean(reset = MockReset.AFTER) private RestTemplate restTemplate;
*/
@Test
public void testOne() throws Exception {
Mockito.when(restTemplate.getForEntity("http://some.weather.api", ObjectNode.class))
.thenReturn(new ResponseEntity("{\"weather\" : \"rainy\"}", HttpStatus.OK));
// Makes call to standard @RestController with a @GetMapping
// Call to external API is contained in @Service class.
// Currently controller just passes through the json from the underlying service call.
this.mockMvc.perform(
get("/weather/check").
contentType(MediaType.APPLICATION_JSON_VALUE)).
andExpect(status().isOk());
}
@Test
public void testTwo() throws Exception {
Mockito.when(restTemplate.getForEntity("http://some.weather.api", ObjectNode.class))
.thenReturn(new ResponseEntity("{\"error\" : \"bandwidth\"}", HttpStatus.BANDWIDTH_LIMIT_EXCEEDED));
this.mockMvc.perform(
get("/weather/check").
contentType(MediaType.APPLICATION_JSON_VALUE)).
andExpect(status().is5xxServerError());
}
}
服务:
@Service
public class WeatherServiceImpl implements WeatherService {
private final RestTemplate restTemplate;
@Autowired
public WeatherServiceImpl(RestTemplate restTemplate) {
this.restTemplate = restTemplate;
}
@Override
public ObjectNode retrieve(URI uri) {
ResponseEntity<ObjectNode> response = restTemplate.getForEntity(uri, ObjectNode.class);
return response.getBody();
}
}
【问题讨论】:
标签: java spring-boot mockito integration-testing