-
Notifications
You must be signed in to change notification settings - Fork 38.5k
Common API for MockMvc tests and for real HTTP tests #19647
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
Comments
Rossen Stoyanchev commented I see where you're coming from but for starters a name such as MockMvc would be a misnomer. More importantly by design it is a server-side test framework that simulates running in a Servlet container with the Spring MVC For an integration test with actual HTTP requests the client and server are much more decoupled and there is little unique value I can see us providing over existing tools such as REST Assured. The general idea is that MockMvc allows you to test thoroughly your Spring MVC controllers and web framework configuration without running a server. Then you should need a lot less full integration testing. |
Neil S commented Thanks, all good points. I do think we ought to have some API which can test both server side and full end to end. Maybe that shouldn't be MockMvc... although I prefer its API over assert and feel that pushing everyone to TestRestTemplate would be a somewhat backward step. How about a (generically named, say 'MvcTest'?) interface that MockMvc implements, which also has an implementation that makes real HTTP requests? You're right that this wouldn't provide functionality not already available elsewhere but it would give the ability to reuse potentially huge amounts of code. At the moment I'm having to decide which tests are important enough to run e2e and duplicate the code using TestRestTemplate. |
Rossen Stoyanchev commented This looks very promising. I did a quick experiment. Essentially just one extra class that wraps a I'm going to schedule tentatively for 5.0 RC1 where we are also planning to put together test support for the spring-web-reactive module and this idea here would be useful to flesh out at this time. Thanks for the suggestion! |
Rossen Stoyanchev commented /cc robwinch and Andy Wilkinson |
Neil S commented Great! Thanks very much :-) |
Rossen Stoyanchev commented This needs to be considered together together with #18391 which comes from a different angle but is also about making MockMvc more broadly usable. A separate concern that needs to be addressed is that many aspects of request building (request + session attributes + anything server-side specific) do not apply to integration tests. How do we deal with that is the question. We could fail fast or ignore those. The same concern is true for expectations matching (model attributes, handler method, etc) but there the matching would naturally fail.. |
Rossen Stoyanchev commented Note also that in 5.0 we have the WebTestClient which as actual client offers a MockMvc-like API that can be used with or without a server. Another route for addressing this ticket would be adapt it to work with both Spring MVC and WebFlux backends. |
Could you please confirm this is still an issue? |
Yes. @rstoyanchev 's experiment in #19647 (comment) looks to be a good solution. |
I'll give this a try for 5.3 RC1. |
After some more thought, while my earlier experiment in #19647 (comment) does work, it has a major issue in that A better path is via Among the benefits of this approach, as an actual HTTP client the I've experimented locally and it is fairly straight forward to do. I should have something concrete this week. What does it mean for existing |
Sounds fair to me, thanks. I've not looked at |
The claimRequest method was not intended to be public and couldn't have been used since the Info type it returned was package private. This change completely hides the Info. See gh-19647
The original behavior was to ignore the body which came with odd warnings in the Javadoc and potential leaks that could be reported from tests causing unnecessary concern. This change causes the body to be released and effectively still ignores it but minus the potential leaks. See gh-19647
WebTestClient is an actual client and generally it's only possible to assert the client response (i.e. what goes over HTTP). However, in a mock server scenario technically we have access to the server request and response and can make those available for further assertions. This will be helpful for the WebTestClient integration with MockMvc where many more assertions can be performed on the server request and response when needed. See gh-19647
Provides parity with similar options in MockMvc: - compare header using a long value - compare header using a date/time value - dedicated method for "Location" header (redirect) - let Hamcrest assert a header even when missing See gh-19647
The new MockMvcTestClient is now available in master with 5.3 snapshots. I've ported all existing sample tests which can be used for comparison. Before:
After
I am keeping the issue open until I've the documentation has been updated.
Use of |
This looks great, thanks! I think it would be useful to add an example that shows best practise to also run the tests from I'm not sure what the neatest way is? Thinking aloud, perhaps the tests could be in an abstract class that is extended by two concrete test classes - one setting up the MockMVCTestClient as shown and the other starting the http server with |
Replace the test client initialization with something like this (and you'll also need to run the server): this.testClient = WebTestClient.bindToServer().baseUrl("http://localhost:8080").build();
Yes that's one way to do it. I suppose it depends on whether you want to run both every time or selectively. It probably makes sense to run in MockMvc mode most often and in live server mode once in a while. If setting things up programmatically you could use JUnit's |
Great thanks. I think it's worth mentioning this in the docs to make it clear how easy it is to do. |
Do we have a reference project with an example of testing rest api with both and live server? if yes please share |
Uh oh!
There was an error while loading. Please reload this page.
Neil S opened SPR-15081 and commented
There seems to be no common API which can be configure to do mock HTTP tests as well as real HTTP tests.
MockMvc tests suffice during development but for production deployment projects might like to do a complete end-to-end integration test by run real tests against a the (maybe embedded) container sever which will be used in production.
At the moment that means writing the same tests twice using the MockMvc and then TestRestTemplate+assert APIs.
IMHO MockMvc has the friendlier API which results in concise and easier to read test code.
Affects: 4.3.5
Issue Links:
0 votes, 6 watchers
The text was updated successfully, but these errors were encountered: