Skip to content

Extract MockHttp from MockMvc [SPR-13818] #18391

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

Closed
spring-projects-issues opened this issue Dec 23, 2015 · 14 comments
Closed

Extract MockHttp from MockMvc [SPR-13818] #18391

spring-projects-issues opened this issue Dec 23, 2015 · 14 comments
Labels
in: test Issues in the test module in: web Issues in web modules (web, webmvc, webflux, websocket) type: enhancement A general enhancement

Comments

@spring-projects-issues
Copy link
Collaborator

spring-projects-issues commented Dec 23, 2015

Rob Winch opened SPR-13818 and commented

Status Quo

The MockMvc support provides an excellent API for testing Spring MVC applications. However, there are users that leverage Spring that may not be using Spring MVC. For example, Spring Security users do not necessarily use Spring MVC.

Without a dedicated API users are forced to manually apply things like RequestPostProcessor, ResultActions, ResultMatchers, etc. Not everything from the MockMvc support can be extracted out, but much of it can.

Proposal

It would be nice if an API that was not dependent on Spring MVC were extracted from MockMvc. A possible name might be MockHttp.


Issue Links:

0 votes, 7 watchers

@spring-projects-issues
Copy link
Collaborator Author

Juergen Hoeller commented

I'd rather have this scheduled for 5.0...

Rossen Stoyanchev, what's your take on this?

Juergen

@spring-projects-issues
Copy link
Collaborator Author

Rossen Stoyanchev commented

Definitely a 5.0. It would be easy to plug any Servlet. That said Spring MVC is in many of the core contracts, anything that takes MvcResult for example. So it might be a little tricky in terms of backwards compatibility. Generally I agree with the description but I'm wondering is there anything specific to motivate this?

@spring-projects-issues
Copy link
Collaborator Author

Rob Winch commented

Thanks for cleaning up the issue Sam Brannen. I did not intend to log this as a bug.

Juergen Hoeller Thanks for the response. I think that a 5.0 candidate would be fine.

That said Spring MVC is in many of the core contracts, anything that takes MvcResult for example. So it might be a little tricky in terms of backwards compatibility

Rossen Stoyanchev I haven't put a lot of thought into this yet, so perhaps you are seeing a problem that I am not. My initial thought was that we would extract an interface that contained the common methods and then make MvcResult extend it. Perhaps something like this:

public interface HttpResult {

	MockHttpServletRequest getRequest();

	MockHttpServletResponse getResponse();
}

public interface MvcResult extends HttpResult {

	Object getHandler();

	HandlerInterceptor[] getInterceptors();

	ModelAndView getModelAndView();

 	Exception getResolvedException();

	FlashMap getFlashMap();

	Object getAsyncResult();

	Object getAsyncResult(long timeToWait);
}

Generally I agree with the description but I'm wondering is there anything specific to motivate this?

The reason is that I have had lots of users ask how to use the Spring Security Test support without Spring MVC. This can work in a limited scope, but is far from ideal. For example, if I want to include a valid CSRF token within a request I can do something like this:

MockHttpServletRequest request = ...;
request = csrf().postProcess(request);

However..

  • Users need to be certain that the MockHttpServletRequest passed in contains the FilterChainProxy reference (either in a WebApplicationContext or a Servlet attribute)
  • It will not function properly if they modify the request after it was post processed. This is because the setup of CSRF token depends on the final value of the HttpServletRequest (since users can map security differently based on the HttpServletRequest).
  • Finally, there is no easy way to say for every MockHttpServletRequest in a set of tests to include a CSRF token.

There are many other pieces of Spring Security's MockMvc integration that would be valuable when users do not use Spring MVC. For example, I love that run a test within MockMvc as a particular user as shown below:

@WithMockUser
public void run() {
    mockMvc.perform(get("/"));
}

This isn't easy when using the FilterChainProxy directly because Spring Security's SecurityContextPersistenceFilter will clear out the SecurityContext that was setup unless it finds a SecurityContext in the HttpServletRequest. We could do something similar to what we demonstrated for CSRF, but we suffer from all the same setbacks.

I happen to be rewriting lots of the Spring Security tests at the moment and find this feature would be appreciated there as well. At the moment I work around the problem by using a stand alone setup with a controller that does nothing. This works for me because I already have an optional Spring MVC dependency, but might not be ideal for users that do not otherwise use Spring MVC.

@spring-projects-issues
Copy link
Collaborator Author

Rossen Stoyanchev commented

The reason is that I have had lots of users ask how to use the Spring Security Test support without Spring MVC.

Okay thanks for the extra detail. I wonder if extracting a subset of Spring MVC Test will necessarily help them? In other words are they manually setting up tests creating a Servlet and Filters, or are they using some test other test framework in which case it becomes more a question of how to make the Spring Security testing support usable outside of Spring MVC Test. In any case it's worth understanding better how this will help them.

@spring-projects-issues
Copy link
Collaborator Author

Rob Winch commented

They are manually setting up the MockFilterChain and using MockHttpServletRequest/MockHttpServletResponse within the MockFilterChain. The assertions are asserting request attributes and properties on the MockHttpServletResponse.

@spring-projects-issues
Copy link
Collaborator Author

Rossen Stoyanchev commented

Okay I see. Feel free to experiment with the contracts to see how easy or hard it might be. It shouldn't take very long to get a sense at least.

@spring-projects-issues
Copy link
Collaborator Author

Andy Wilkinson commented

This could be of interest to Spring REST Docs too. I currently have an abstraction that's implemented for both MockMvc and REST Assured. See https://github.com/spring-projects/spring-restdocs/blob/master/spring-restdocs-core/src/main/java/org/springframework/restdocs/operation/Operation.java and its related types. Its design is almost certainly too REST Docs-specific, but perhaps it's a useful datapoint nonetheless. I'd gladly get rid of it in the REST Docs 2.0 / Spring Framework 5.0 timeframe.

@spring-projects-issues
Copy link
Collaborator Author

Rob Winch commented

I've started the work on this in https://github.com/rwinch/spring-framework/tree/SPR-13818-mockhttp

NOTE: The branch is just a start (not nearly complete) and likely to be rebased changed etc.

@spring-projects-issues
Copy link
Collaborator Author

Rob Winch commented

I've pushed some updates to this in the same branch https://github.com/rwinch/spring-framework/tree/SPR-13818-mockhttp I'd love some feedback on if you think this is headed in the right direction or not Rossen Stoyanchev

@spring-projects-issues
Copy link
Collaborator Author

Rossen Stoyanchev commented

Andy Wilkinson from your perspective is it mainly about getting rid of Operation? Looking at that interface and related abstractions in the same package that goes a little deeper in representing the request and response in a framework independent way.

In this ticket there is no intent to abstract the use of the MockHttpServletRequest and Response. It's mainly about using any Servlet and also without dependency on spring-webmvc.

@spring-projects-issues
Copy link
Collaborator Author

Andy Wilkinson commented

Yes, my interest was in possibly getting rid of Operation. Your right that it does go deeper. I initially tried to use MockHttpServletRequest and MockHttpServletResponse but they didn't give me exactly what I needed. I was wondering if this was perhaps an opportunity to address that, but it sounds like the requirements don't quite line up.

@spring-projects-issues spring-projects-issues added in: test Issues in the test module type: enhancement A general enhancement in: web Issues in web modules (web, webmvc, webflux, websocket) labels Jan 11, 2019
@spring-projects-issues spring-projects-issues added this to the 5.x Backlog milestone Jan 11, 2019
@wagnerluis1982
Copy link

What is the status for this issue?

@rstoyanchev
Copy link
Contributor

@wagnerluis1982 it's in the 5.x Backlog. Can you describe your use case?

@jhoeller jhoeller modified the milestones: 5.x Backlog, General Backlog Aug 24, 2020
@rstoyanchev
Copy link
Contributor

I'm closing this as we have no plans to work on it.

@rstoyanchev rstoyanchev closed this as not planned Won't fix, can't repro, duplicate, stale Feb 7, 2024
@jhoeller jhoeller removed this from the General Backlog milestone Feb 7, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: test Issues in the test module in: web Issues in web modules (web, webmvc, webflux, websocket) type: enhancement A general enhancement
Projects
None yet
Development

No branches or pull requests

4 participants