当其余模板具有使用Spring boot 1.5.x 的拦截器时,我们可以使用@RestClientTest 吗?
Can we use @RestClientTest when the rest template has interceptors using Spring boot 1.5.x?
我正在使用 Spring Boot 1.5.x (Spring 4.2.x),我创建了一个 RestClientSdk spring 组件 class 如下所示:
@Component
public class RestClientSdkImpl implements RestClientSdk {
private RestTemplate restTemplate;
@Autowired
public RestClientSdkImpl(RestTemplateBuilder restTemplateBuilder) {
this.restTemplate = restTemplateBuilder.build();
}
...
//other methods kept out for brevity
}
我还定义了 DefaultRestTemplateCustomizer spring 组件,如下所示:
@Component
public class DefaultRestTemplateCustomizer implements RestTemplateCustomizer {
private LogClientHttpRequestInterceptor logClientHttpRequestInterceptor;
@Autowired
public DefaultRestTemplateCustomizer(LogClientHttpRequestInterceptor logClientHttpRequestInterceptor) {
this.logClientHttpRequestInterceptor = logClientHttpRequestInterceptor;
}
@Override
public void customize(RestTemplate restTemplate) {
restTemplate.getInterceptors().add(logClientHttpRequestInterceptor);
restTemplate.setRequestFactory(new BufferingClientHttpRequestFactory(new SimpleClientHttpRequestFactory()));
}
}
有了这个,我定义了一个测试 class,如下所示,它使用 @RestClientTest 注释,如下所示。
@RunWith(SpringRunner.class)
@RestClientTest(RestClientSdk.class)
@ActiveProfiles("test")
/*
* The RestClientTest only includes the most minimal configuration to include a rest template builder,
* so we include the rest sdk auto config within the scope of the test
*/
@ImportAutoConfiguration(RestSdkAutoConfiguration.class)
public class RestClientApplicationBehaviourTest{
@Autowired
private RestClientSdk restClientSdk;
@Autowired
private MockRestServiceServer mockRestServiceServer;
/**
* A simple Http Get that retrieves a JSON document from a rest server and
* produces a plain old java object as a response.
*/
@Test
public void testPlainHttpGet() throws IOException{
//ARRANGE
RestClientDto<?> simpleGetRequest = simpleHttpGet();
mockRestServiceServer.expect(once(), requestTo("http://localhost:8080/account/1234567890"))
.andRespond(withSuccess(IOUtils.getInputAsString("/stubs/account.json"),MediaType.APPLICATION_JSON));
//ACT
Account account = restClientSdk.send(simpleGetRequest, Account.class);
//ASSERT
mockRestServiceServer.verify();
Assert.assertNotNull(account);
Assert.assertNotNull(account.getAccountId());
Assert.assertNotNull(account.getFirstName());
Assert.assertNotNull(account.getLastName());
}
...
//not including other methods for brevity
}
问题
因为 MockRestServiceServer 构建器用 MockClientHttpRequestFactory 覆盖了我的 rest 模板中的 BufferingClientHttpRequestFactory,所以我从我的 body 得到了一个空响应。这是因为日志记录拦截器正在读取来自响应的输入流,因此该流不再有要读取的内容。 BufferingClientHttpRequestFactory 会阻止这种情况的发生。现在,我知道从 Spring 5.0.5 开始,MockRestServiceServer 构建器中有一个名为 bufferContent 的额外选项,但我没有移动到 Spring 5.x (Spring Boot 2.x),所以我想知道是否有办法使用 Spring Boot 1.5.x 进行配置/ Spring 4.2.x.
先谢谢你了!
胡安
为了解决这个问题,我需要定义一个测试配置,这样我就可以覆盖客户端请求工厂。请看下面的代码。这有点老套,但我想真正的解决方案是升级到 Spring 5.x / Spring Boot 2.x.
@Configuration
@Profile("test")
public class MockRestServiceServerConfiguration {
/**
* Wrap the Mock Rest client factory in the buffered one.
* @param restClientSdk The rest client SDK containing the rest template to use.
* @return The mock rest service server to use.
*/
@Bean
public MockRestServiceServer mockRestServiceServer(RestClientSdkImpl restClientSdkImpl) {
RestTemplate restTemplate = restClientSdkImpl.getRestTemplate();
MockRestServiceServer server = MockRestServiceServer.createServer(restTemplate);
//need to do this because getRequestFactory returns InterceptingHttpRequestFactory wraping the mock rest service server request factory
List<ClientHttpRequestInterceptor> templateInterceptors = restTemplate.getInterceptors();
restTemplate.setInterceptors(null);
//now we wrap the delegate, which should be the mock rest service server request factory
BufferingClientHttpRequestFactory bufferingFact = new BufferingClientHttpRequestFactory(restTemplate.getRequestFactory());
restTemplate.setRequestFactory(bufferingFact);
restTemplate.setInterceptors(templateInterceptors);
return server;
}
}
我正在使用 Spring Boot 1.5.x (Spring 4.2.x),我创建了一个 RestClientSdk spring 组件 class 如下所示:
@Component
public class RestClientSdkImpl implements RestClientSdk {
private RestTemplate restTemplate;
@Autowired
public RestClientSdkImpl(RestTemplateBuilder restTemplateBuilder) {
this.restTemplate = restTemplateBuilder.build();
}
...
//other methods kept out for brevity
}
我还定义了 DefaultRestTemplateCustomizer spring 组件,如下所示:
@Component
public class DefaultRestTemplateCustomizer implements RestTemplateCustomizer {
private LogClientHttpRequestInterceptor logClientHttpRequestInterceptor;
@Autowired
public DefaultRestTemplateCustomizer(LogClientHttpRequestInterceptor logClientHttpRequestInterceptor) {
this.logClientHttpRequestInterceptor = logClientHttpRequestInterceptor;
}
@Override
public void customize(RestTemplate restTemplate) {
restTemplate.getInterceptors().add(logClientHttpRequestInterceptor);
restTemplate.setRequestFactory(new BufferingClientHttpRequestFactory(new SimpleClientHttpRequestFactory()));
}
}
有了这个,我定义了一个测试 class,如下所示,它使用 @RestClientTest 注释,如下所示。
@RunWith(SpringRunner.class)
@RestClientTest(RestClientSdk.class)
@ActiveProfiles("test")
/*
* The RestClientTest only includes the most minimal configuration to include a rest template builder,
* so we include the rest sdk auto config within the scope of the test
*/
@ImportAutoConfiguration(RestSdkAutoConfiguration.class)
public class RestClientApplicationBehaviourTest{
@Autowired
private RestClientSdk restClientSdk;
@Autowired
private MockRestServiceServer mockRestServiceServer;
/**
* A simple Http Get that retrieves a JSON document from a rest server and
* produces a plain old java object as a response.
*/
@Test
public void testPlainHttpGet() throws IOException{
//ARRANGE
RestClientDto<?> simpleGetRequest = simpleHttpGet();
mockRestServiceServer.expect(once(), requestTo("http://localhost:8080/account/1234567890"))
.andRespond(withSuccess(IOUtils.getInputAsString("/stubs/account.json"),MediaType.APPLICATION_JSON));
//ACT
Account account = restClientSdk.send(simpleGetRequest, Account.class);
//ASSERT
mockRestServiceServer.verify();
Assert.assertNotNull(account);
Assert.assertNotNull(account.getAccountId());
Assert.assertNotNull(account.getFirstName());
Assert.assertNotNull(account.getLastName());
}
...
//not including other methods for brevity
}
问题
因为 MockRestServiceServer 构建器用 MockClientHttpRequestFactory 覆盖了我的 rest 模板中的 BufferingClientHttpRequestFactory,所以我从我的 body 得到了一个空响应。这是因为日志记录拦截器正在读取来自响应的输入流,因此该流不再有要读取的内容。 BufferingClientHttpRequestFactory 会阻止这种情况的发生。现在,我知道从 Spring 5.0.5 开始,MockRestServiceServer 构建器中有一个名为 bufferContent 的额外选项,但我没有移动到 Spring 5.x (Spring Boot 2.x),所以我想知道是否有办法使用 Spring Boot 1.5.x 进行配置/ Spring 4.2.x.
先谢谢你了!
胡安
为了解决这个问题,我需要定义一个测试配置,这样我就可以覆盖客户端请求工厂。请看下面的代码。这有点老套,但我想真正的解决方案是升级到 Spring 5.x / Spring Boot 2.x.
@Configuration
@Profile("test")
public class MockRestServiceServerConfiguration {
/**
* Wrap the Mock Rest client factory in the buffered one.
* @param restClientSdk The rest client SDK containing the rest template to use.
* @return The mock rest service server to use.
*/
@Bean
public MockRestServiceServer mockRestServiceServer(RestClientSdkImpl restClientSdkImpl) {
RestTemplate restTemplate = restClientSdkImpl.getRestTemplate();
MockRestServiceServer server = MockRestServiceServer.createServer(restTemplate);
//need to do this because getRequestFactory returns InterceptingHttpRequestFactory wraping the mock rest service server request factory
List<ClientHttpRequestInterceptor> templateInterceptors = restTemplate.getInterceptors();
restTemplate.setInterceptors(null);
//now we wrap the delegate, which should be the mock rest service server request factory
BufferingClientHttpRequestFactory bufferingFact = new BufferingClientHttpRequestFactory(restTemplate.getRequestFactory());
restTemplate.setRequestFactory(bufferingFact);
restTemplate.setInterceptors(templateInterceptors);
return server;
}
}