New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add ExecutingResponseCreator to delegate request and response #29721
Add ExecutingResponseCreator to delegate request and response #29721
Conversation
This commit adds the andPerformRequest method to ResponseActions, which is in effect activating a ResponseCreator that has been implicitly defined for relevant implementations. Implementations without explicit support for this will throw an UnsupportedOperationException by default. The SimpleRequestExpectationManager and UnorderedRequestExpectationManager created in `MockRestServiceServerBuilder#build()` capture and use the original ClientHttpRequestFactory, setting up an implicit ResponseCreator that executes an actual request and returns the response. Fixes spring-projectsgh-26381.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for putting this together based on the discussion under #26381. Looking at the result, I'm wondering if it wouldn't be more idiomatic to simply provide a ResponseCreator
implementation instead:
public class ExecutingResponseCreator implements ResponseCreator {
private final ClientHttpRequestFactory requestFactory;
public ExecutingResponseCreator(RestTemplate restTemplate) {
this.requestFactory = restTemplate.getRequestFactory();
}
@Override
public ClientHttpResponse createResponse(ClientHttpRequest request) throws IOException {
Assert.state(request instanceof MockClientHttpRequest, "Expected mock request");
MockClientHttpRequest mockRequest = (MockClientHttpRequest) request;
ClientHttpRequest newRequest = this.requestFactory.createRequest(mockRequest.getURI(), mockRequest.getMethod());
newRequest.getHeaders().putAll(mockRequest.getHeaders());
StreamUtils.copy(mockRequest.getBodyAsBytes(), newRequest.getBody());
return newRequest.execute();
}
}
which is then used:
ResponseCreator executingResponseCreator = new ExecutingResponseCreator(restTemplate);
MockRestServiceServer server = MockRestServiceServer.bindTo(restTemplate).build();
...
server.expect(requestTo("/foo")).andRespond(withSuccess());
server.expect(requestTo("/bar")).andRespond(executingResponseCreator);
The rest of the code, MockRestServiceServer
, ResponseActions
, RequestExpectationManager
implementations would remain unaware of any of this, which simplifies the implementation, and is generally easier to understand how it fits.
It would provide extra flexibility too because it becomes just another ResponseCreator
that's no different from the rest. I'm thinking, we could provide an option for setting a default ResponseCreator
in the MockRestServiceServer
builder. That's independently useful, but if set to the ExecutingResponseCreator
it would execute requests by default when andResponse
isn't called. That's the effect that was sought in the original comment under #26381.
This reverts commit 3a334a5.
This commit adds a new convenience `ResponseCreator` implementation that delegates to a `ClientHttpRequestFactory` to perform a request and use the response. For further convenience, a factory method based on a `RestTemplate` is also added: `MockRestResponseCreators#byExecutingRequestUsing`. This acts as a pseudo-DSL for fluently setting the ResponseCreator in a `ResponseActions`. The primary purpose of this implementation is to perform an actual request to an external service and use the response in MockMVC. Closes spring-projectsgh-26381
@rstoyanchev I have reverted the previous implementation and introduced |
mmh I realize just now that the factory method in I wonder how to improve the discoverability of the feature 🤔 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks that looks very nice and simple.
For the visibility, we could:
- add a paragraph in the Javadoc for
MockRestResponseCreator
that links to the alternativeExecutingResponseCreator
along with an@see
reference. - add something in the reference docs under this section.
- yet another option is to add a sample test to the ones mentioned here, and that could use
MockWebServer
like inWebClientIntegrationTests
for example
...est/src/main/java/org/springframework/test/web/client/response/ExecutingResponseCreator.java
Show resolved
Hide resolved
This commit adds a new `ResponseCreator` implementation that uses a `ClientHttpRequestFactory` to perform an actual request. Closes spring-projectsgh-29721
This commit adds a new convenience
ResponseCreator
implementation thatdelegates to a
ClientHttpRequestFactory
to perform a request anduse the response.
For further convenience, a factory method based on a
RestTemplate
isalso added:
MockRestResponseCreators#byExecutingRequestUsing
. Thisacts as a pseudo-DSL for fluently setting the ResponseCreator in a
ResponseActions
.The primary purpose of this implementation is to perform an actual
request to an external service and use the response in MockMVC.
Closes gh-26381