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 mock-like handler method reference in Spring MVC Test [SPR-13736] #18309

Closed
spring-projects-issues opened this issue Nov 29, 2015 · 7 comments
Assignees
Labels
in: test Issues in the test module in: web Issues in web modules (web, webmvc, webflux, websocket) type: enhancement A general enhancement
Milestone

Comments

@spring-projects-issues
Copy link
Collaborator

spring-projects-issues commented Nov 29, 2015

Manuel Jordan opened SPR-13736 and commented

The HandlerResultMatchers class contains various methodName(...) methods for validating that a particular method was invoked on the handler (i.e., controller); however, each such methodName(...) method currently requires a hard coded String or a reflection-based Method (which indirectly also requires a hard coded String).

Please add support for mocking a @RequestMapping method in a @Controller similar to how MvcUriComponentsBuilder works.

Something like this:

.andExpect(handler().method(
    fromMethodCall(on(PersonaXmlFindOneController.class).findOnePathVariableById(...))
)

The purpose is to avoid hard coding method names as strings like in the following:

.andExpect(handler().methodName("findOnePathVariableById"))
.andExpect(handler().methodName(is("findOnePathVariableById")))

If someone refactors a controller and renames a @RequestMapping method, the above expectations will then fail since the hard coded method names do not get updated as part of the refactoring.

Note: it should ignore the arguments to be passed. The point is only confirm the method has been called/executed.

Therefore perhaps a similar syntax as shown below would be nice

.andExpect(handler().methodCalled(
ControllerSomethingBuilder.methodOn(PersonaXmlFindOneController.class).findOnePathVariableById())

Affects: 4.2 GA

Referenced from: commits 4b11835

@spring-projects-issues
Copy link
Collaborator Author

spring-projects-issues commented Nov 30, 2015

Sam Brannen commented

.andExpect(handler().methodCalled(
ControllerSomethingBuilder.methodOn(PersonaXmlFindOneController.class).findOnePathVariableById())

FYI: the above could only possibly work if such a method exists. It's not possible to invoke a method (even via a mock) if you leave out required method arguments.

@spring-projects-issues
Copy link
Collaborator Author

spring-projects-issues commented Dec 1, 2015

Manuel Jordan commented

Hi Sam

FYI: the above could only possibly work if such a method exists

Has sense. Otherwise the compiler can't detect or does not valid that sentence. Until here I am fine.

It's not possible to invoke a method (even via a mock) if you leave out required method arguments.

Ok. What I understand is that is mandatory send the argument to the method. Am I correct?

Something to consider (perhaps other issue to create). For Spock Reports I think valuable add the following (in some way)

ControllerSomethingBuilder
     .methodOn(PersonaXmlFindOneController.class)
     .findOnePathVariableById()
     .getMethodName() // <----

See above the .getMethodName()

Therefore
(1) Confirm the method of an controller has been executed/called
(2) Get the method controller name that has been executed (it for reports)

@spring-projects-issues
Copy link
Collaborator Author

spring-projects-issues commented Jan 7, 2016

Rossen Stoyanchev commented

This could be done even now:

public class ResponseBodyTests {

	@Test
	public void json() throws Exception {
		standaloneSetup(new PersonController()).build()
				.perform(get("/person/Lee").accept(MediaType.APPLICATION_JSON))
				.andExpect(methodCall(on(PersonController.class).get(null)));
	}

	public ResultMatcher methodCall(Object info) {

		return new ResultMatcher() {
			@Override
			public void match(MvcResult result) throws Exception {
				Method method = ((MvcUriComponentsBuilder.MethodInvocationInfo) result).getControllerMethod();
				handler().method(method);
			}
		};
	}



	@Controller
	private class PersonController {

		@RequestMapping(value="/person/{name}")
		@ResponseBody
		public Person get(@PathVariable String name) {
			return new Person(name);
		}
	}
}

For 4.3 we could support the above methodCall directly in HandlerResultMatchers.

@spring-projects-issues
Copy link
Collaborator Author

spring-projects-issues commented Jan 7, 2016

Sam Brannen commented

Rossen Stoyanchev, that sounds good. Go for it!

@spring-projects-issues
Copy link
Collaborator Author

spring-projects-issues commented Jan 7, 2016

Manuel Jordan commented

Very interesting the code.

For 4.3 we could support the above methodCall directly in HandlerResultMatchers.
I am going to wait that new improvement and its respective documentation/example.

Without be rude and respecting your (you all team) hard work.
Is possible improve (get the method name) for Testing reports?
It for JUnit and/or for Spock Reports.

Kind Regards

@spring-projects-issues
Copy link
Collaborator Author

spring-projects-issues commented Jan 7, 2016

Rossen Stoyanchev commented

Is possible improve (get the method name) for Testing reports?

What do you have in mind?

@spring-projects-issues
Copy link
Collaborator Author

spring-projects-issues commented Jan 15, 2016

Rossen Stoyanchev commented

See commit 4b1183.

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

2 participants