我有一个REST资源,该资源获取RestTemplateBuilder
注入以构建RestTemplate
:
public MyClass(final RestTemplateBuilder restTemplateBuilder) {
this.restTemplate = restTemplateBuilder.build();
}
我想测试那堂课。我需要模拟
RestTemplate
对另一个服务的调用:request = restTemplate.getForEntity(uri, String.class);
我在IT部门尝试过此操作:
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class MyIT {
@Autowired
private TestRestTemplate testRestTemplate;
@MockBean
private RestTemplateBuilder restTemplateBuilder;
@Mock
private RestTemplate restTemplate;
@Test
public void shouldntFail() throws IOException {
ResponseEntity<String> responseEntity = new ResponseEntity<>(HttpStatus.NOT_FOUND);
when(restTemplateBuilder.build()).thenReturn(restTemplate);
when(restTemplate.getForEntity(any(URI.class), any(Class.class))).thenReturn(responseEntity);
...
ResponseEntity<String> response = testRestTemplate.postForEntity("/endpoint", request, String.class);
...
}
}
运行测试时,出现以下异常:
java.lang.IllegalStateException: Failed to load ApplicationContext
...
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.boot.test.web.client.TestRestTemplate': Initialization of bean failed; nested exception is java.lang.IllegalArgumentException: RestTemplate must not be null
如何正确执行此操作?
最佳答案
您的问题是执行顺序。在您有机会在MockBean
中进行设置之前,将创建包含@Test
的上下文。解决方案是提供一个RestTemplateBuilder
,将其插入上下文时已完全设置。您可以这样做。
将以下内容添加到@SpringBootTest
批注中。其中TestApplication
是您的Spring Boot应用程序类。
classes = {TestApplication.class, MyIT.ContextConfiguration.class},
因此,修改类成员,删除restTemplate和restTemplateBuilder。
@Autowired
private TestRestTemplate testRestTemplate;
在您的
MyIT
类中添加一个静态内部类:@Configuration
static class ContextConfiguration {
@Bean
public RestTemplateBuilder restTemplateBuilder() {
RestTemplateBuilder rtb = mock(RestTemplateBuilder.class);
RestTemplate restTemplate = mock(RestTemplate.class);
when(rtb.build()).thenReturn(restTemplate);
return rtb;
}
}
在测试中,修改
RestTemplate
模拟以执行所需的任何操作:@Test
public void someTest() {
when(testRestTemplate.getRestTemplate().getForEntity(...
}