Skip to content
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

Support of MockRestServiceServer for WebClient [SPR-15286] #19852

Closed
spring-issuemaster opened this issue Feb 24, 2017 · 22 comments

Comments

@spring-issuemaster
Copy link
Collaborator

@spring-issuemaster spring-issuemaster commented Feb 24, 2017

Stéphane Nicoll opened SPR-15286 and commented

Spring Boot has a @RestClientTest for pure client-side tests. We currently auto-configure MockRestServiceServer and bind any RestTemplate created by the RestTemplateBuilder to it.

This would be pretty awesome if we could port that feature to WebClient transparently if webflux is on the classpath. That would require that MockRestServiceServer can be configured with a WebClient in addition to a RestTemplate


Sub-tasks:

  • #19295 Document how to test WebClient code with a mock server

15 votes, 24 watchers

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

@spring-issuemaster spring-issuemaster commented Feb 27, 2017

Rossen Stoyanchev commented

Indeed we'll most certainly need that. I'm putting it in the 5.1 backlog for now since I don't expect we'll manage that for 5.0.

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

@spring-issuemaster spring-issuemaster commented Nov 1, 2017

Rossen Stoyanchev commented

In the mean time I suggest using the OkHttp MockWebServer (or similar) as do in our own WebClientIntegrationTests.

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

@spring-issuemaster spring-issuemaster commented Mar 12, 2018

Rob Worsnop commented

OkHttp was not a good substitute for us, so we created a temporary drop-in replacement for MockRestServiceServer. It, along with supporting classes, is here: https://github.com/vmware/connectors-workspace-one/tree/master/common/connectors-test/src/main/java/com/vmware/connectors/mock

Example usage here: https://github.com/vmware/connectors-workspace-one/blob/master/connectors/jira/src/test/java/com/vmware/connectors/jira/JiraControllerTests.java

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

@spring-issuemaster spring-issuemaster commented Mar 12, 2018

Rossen Stoyanchev commented

What did you run into, i.e. where did using OkHttp fall short?

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

@spring-issuemaster spring-issuemaster commented Mar 12, 2018

Rob Worsnop commented

Our code does a parallel scatter-gather and aggregates the results. Because OkHttp is a "real" HTTP server, we get those results in a non-deterministic order, which makes it hard to match actual results to expected results.

I think I got around that by sorting the results with Flux.sort (in the production code, not tests) but then there was another problem: Our server returns JSON with hyperlinks pointing to the back-end it's accessing. With MockRestServiceServer, our code thinks it's talking to "http://bogus-host" and reliably formats links accordingly. With OkHttp, our server knows it's talking to "http://localhost:<random_port>", with the port changing with every test. Again, we can't easily match actual results to expected results.

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

@spring-issuemaster spring-issuemaster commented Mar 13, 2018

Rossen Stoyanchev commented

Thanks for the feedback. Would JSONPath help in this scenario, i.e. dealing with data in non-deterministic order, and also parameterizing the host and port? On the flip side processing scatter gather in true random fashion probably makes for more realistic tests, which is desirable as long as it doesn't bring undue burden.

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

@spring-issuemaster spring-issuemaster commented Mar 13, 2018

Rob Worsnop commented

I thought I could probably work around all of the issues somehow, but at some point I realized that creating a WebClient-compatible mock was going to end up being easier.
Also, switching from AsyncRestTemplate to WebClient was a fairly major change, so being able to use virtually the same tests as before was pretty important. It gave us reassurance that behavior hadn't changed.

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

@spring-issuemaster spring-issuemaster commented Mar 14, 2018

Rossen Stoyanchev commented

Good to know, thanks!

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

@spring-issuemaster spring-issuemaster commented Mar 29, 2018

Rob Worsnop commented

Quick update: I just used WebTestClient/OkHttp on a new project. It does seem much better than MockMvc/MockRestServiceServer.

One thing I noticed is that ordering in JSON arrays doesn't matter because I'm calling expectBody().json() on WebTestClient. Then I went back and noticed that we're calling content().string in the old code instead of content().json. (The reasons for doing this aren't entirely stupid, but they aren't that great either.)

Now I'm wondering if rewriting the old tests using WebTestClient/OkHttp might be the best way forward, now that the old tests have confirmed that moving to WebClient hasn't broken anything.

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

@spring-issuemaster spring-issuemaster commented Mar 30, 2018

Rossen Stoyanchev commented

It would be useful to confirm if there are any specific issues in transitioning those tests. That is if you find the time the time for that exercise :)

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

@spring-issuemaster spring-issuemaster commented Nov 15, 2018

Craig Skinfill commented

any plans to implement this?  its making adopting WebFlux and WebClient harder since we can't test the same way we could with RestTemplate

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

@spring-issuemaster spring-issuemaster commented Nov 16, 2018

Rossen Stoyanchev commented

Craig Skinfill, given the existence of the MockWebServer and others like WireMock, the idea is we might never build a MockRestServiceServer equivalent. I realize we have work to do to make this more clear in the docs, and to add some testing support for this in Spring Boot, but as far a direction, in the absence of any compelling reasons to build our own solution, MockWebServer (or similar mock server) is the present day alternative to MockRestServiceServer.

I have not done a complete analysis and comparison but it's clear that MockWebServer is in the same space and serves the same purpose, but is more widely applicable to any HTTP client, because it's exposed over HTTP through communication over a socket. So instead of using some sort of mock ClientHttpConnector with canned responses, you get to keep the HTTP client underneath (e.g. ReactorClientHttpConnector) and that leads to more complete testing. Over an actual socket it's more natural to simulate slow network conditions, chunked responses, and the like, and then in turn to test the impact with the actual HTTP client in charge of processing content on the wire. Even if we did create our own solution again, I'd consider strongly a similar approach but then again, why re-create what's available? Last but not least, it's worth mentioning also that MockWebServer has a large community which is important for maturity, learning resources, and feedback from diverse use cases.

 

 

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

@spring-issuemaster spring-issuemaster commented Nov 17, 2018

Craig Skinfill commented

Rossen Stoyanchev thanks for the explanation.  that makes sense to me.  Is there a preferred, from spring reactor perspective, mock server to consider?  Or any that have a closer integration with spring?

 

Thanks again.

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

@spring-issuemaster spring-issuemaster commented Nov 20, 2018

Rossen Stoyanchev commented

Craig Skinfill we're using MockWebServer for our own tests, and it suits our needs so far. I don't have experience with others.

I think we probably need to think about Boot support for integration tests for code that uses the WebClient. Brian Clozel should we create a ticket for that in Boot to explore what such support could look like? Aside from that I don't see much need for Spring-specific configuration since client and server communicate over a socket, they're pretty decoupled.

@membersound

This comment has been minimized.

Copy link

@membersound membersound commented Jul 24, 2019

Using WebClient for client-side requests is pretty useless if there is no proper mock in spring for testing our code. Having rewritten my RestTemplate client code to WebClient, I'm disappointed there is no replacement for MockRestServiceServer yet...

@dsundarraj2

This comment has been minimized.

Copy link

@dsundarraj2 dsundarraj2 commented Jul 24, 2019

@membersound

This comment has been minimized.

Copy link

@membersound membersound commented Jul 24, 2019

While this might work, I'd prefer relying on some kind of "official" framework, eg something that's included and maintained by spring themselves. Otherwise, if WebClient evolves by time, and WireMock is left behind, that might led to rewrites for all of my projects. As we all know, time is money, so that's too risky...

@rstoyanchev

This comment has been minimized.

Copy link
Contributor

@rstoyanchev rstoyanchev commented Jul 25, 2019

@membersound I appreciate the point but there is also a lot of effort involved to create, maintain, and evolve something over time and it's hard to justify given the existing alternatives. HTTP provides loose coupling so implementations can exist and evolve independently. In this case we're even talking about mocking a server and shaping its behavior. I should think that switching from one to another shouldn't be as big a deal as it might seem at first. That said MockWebServer has more stars than the Spring Framework does and I don't think it is going to be a problem with longevity.

@SFBorland

This comment has been minimized.

Copy link

@SFBorland SFBorland commented Oct 3, 2019

Is it listed somewhere in the official docs that MockWebServer is the recommended solution? I've spent a few days now looking for an official Spring version or trying to get existing stuff to work and finally stumbled on this thread..

@bclozel

This comment has been minimized.

@SFBorland

This comment has been minimized.

Copy link

@SFBorland SFBorland commented Oct 3, 2019

@bclozel I see it now...thanks.

@rstoyanchev rstoyanchev removed this from the 5.x Backlog milestone Nov 15, 2019
@rstoyanchev

This comment has been minimized.

Copy link
Contributor

@rstoyanchev rstoyanchev commented Nov 15, 2019

Closing as we have no further plans at this time.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
6 participants
You can’t perform that action at this time.