首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用“restTemplate restTemplate”理解@MockBean的用法

用“restTemplate restTemplate”理解@MockBean的用法
EN

Stack Overflow用户
提问于 2021-09-23 21:15:23
回答 1查看 638关注 0票数 1

当模拟的NullPointerException调用时,我看到的行为是第二个测试中的一个restTemplate。这指出了一个问题,在重置模拟。令我惊讶的是修复(使两个测试都通过了)。

将代码从@MockBean private RestTemplate restTemplate;修改为@MockBean(reset = MockReset.NONE) private RestTemplate restTemplate;解决了这个问题。这里有几个问题:

  1. 为什么MockReset.RESET的默认@MockBean行为不能工作?
  2. :我设置测试的方式有问题吗?默认的MockReset.RESET失败了吗?
  3. 测试配置类有问题吗?

希望我已经提供了足够的上下文来回答这个问题。

我已经创建了一个我所看到的简单示例:测试配置:

代码语言:javascript
复制
@Profile("test")
@Configuration
public class TestConfiguration {

    @Bean
    @Primary
    public ObjectNode getWeatherService(RestTemplate restTemplate) {
        return new WeatherServiceImpl(restTemplate);
    }

}

测试:

代码语言:javascript
复制
@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());
    }
}

服务:

代码语言:javascript
复制
@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();
    }

}
EN

回答 1

Stack Overflow用户

发布于 2021-09-24 16:26:08

对于@MockBean的默认行为存在误解:

为什么MockReset.RESET的默认@MockBean行为不起作用?我设置测试的方式有问题吗?默认的MockReset.RESET失败了吗?

来自MockBean.reset方法文档:

重置模式以应用于模拟bean。默认情况是MockReset.AFTER,这意味着在调用每个测试方法之后,将自动重置模拟。

因此,在执行第一个测试案例之后,您的MockBean将被重置并从应用程序上下文中取消注册,然后您的第二个测试案例将发现它为null,而在@MockBean(reset = MockReset.NONE)情况下不会像您所做的那样发生这种情况。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69306972

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档