Reputation: 219
I am using:
I am trying to write a junit test case for a controller with RedirectAttributes.
Controller's signature is:
@RequestMapping(method = RequestMethod.POST)
public String homePOST(@Validated({ IBasic.class }) @ModelAttribute("userCommand") User userCommand,
BindingResult result, Model model,
RedirectAttributes flashAttributes)
JUnit test case is:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "/root-context.xml", "/servlet-context.xml" })
public class HomeControllerTest {
@Autowired
private RequestMappingHandlerAdapter handlerAdapter;
@Autowired
private RequestMappingHandlerMapping handlerMapping;
@Test
public void testHomePOST() {
MockHttpServletRequest request = new MockHttpServletRequest("POST", "/");
request.addParameter("username", "user1");
request.addParameter("password", "mypasswd");
MockHttpServletResponse response = new MockHttpServletResponse();
Object handler;
try {
handler = handlerMapping.getHandler(request).getHandler();
ModelAndView modelAndView = handlerAdapter.handle(request,
response, handler);
assertViewName(modelAndView, "redirect:/myview");
} catch (Exception e) {
String err = "Error executing controller : " + e.toString();
fail(err);
}
}
}
When handlerAdapter.handle() is executed, i am getting :
java.lang.AssertionError: Error executing controller : java.lang.NullPointerException
at org.junit.Assert.fail(Assert.java:93)
at com.myapps.service.impl.test.HomeControllerTest.testHomePOST(HomeControllerTest.java:75)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:45)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:83)
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:231)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:47)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71)
at org.junit.runners.ParentRunner.run(ParentRunner.java:300)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:174)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
If i remove the RedirectAttributes from the controller, it is working properly.
Can anyone please provide some help how to test a controller with RedirectAttributes?
Thank you in advance.
In order to simulate this, here is the controller code:
@Controller
@RequestMapping(value = "/")
public class HomeController {
@RequestMapping(method = RequestMethod.POST)
public String homePOST(
@Validated({ IBasic.class }) @ModelAttribute("userCommand") User userCommand,
BindingResult result, Model model,
RedirectAttributes flashAttributes) {
return "redirect:/myview";
}
}
Upvotes: 2
Views: 7847
Reputation: 223
Use mockito framework to mock it. use
RedirectAttributes flashAttributes;
flashAttributes=Mockito.mock(RedirectAttributes.class)
in the setup function.
Upvotes: 0
Reputation: 49935
I am able to replicate your issue - the underlying reason for the issue is that if a RedirectAttributes is present as a handler method parameter, then just before returning from the handler adapter, the output "flashmap" is pulled and the flashAttributes added to it. Now, this output flashMap is retrieved from the httprequest - in your case, this is null for your MockHttpServletRequest
.
The fix is to simply set a dummy output flashMap in the MockHttpServletRequest:
request.setAttribute(DispatcherServlet.OUTPUT_FLASH_MAP_ATTRIBUTE,new FlashMap());
This works for me now. Can you please try and see if it fixes this issue for you.
Upvotes: 5