JUnit test for Spring controller. Expected "200", but was "404" - spring-mvc

I am trying to test my Spring MVC controller with JUnit and I get this:
java.lang.AssertionError: Status expected:<200> but was:<404>
I guess my JUnit setup for controller tests isn't working like it should, but I really can't point out where the mistake is. I've read so many tutorials about this that it's getting frustrating.
This is simplyfied version of my LoginController class, but it will be enough
#Controller
public class LoginController {
#Autowired
private DAO dao;
#RequestMapping(value = "username", method = RequestMethod.GET)
public String GetUsername(Model model){
model.addAttribute("username", dao.getUsername());
return "login"; //login.jsp
}
And this is JUnit class which is testing that controller:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration("file:src/main/webapp/WEB-INF/Spring-Context.xml")
public class LoginControllerTest {
#Mock
private DAO dao;
#InjectMocks
LoginController controller;
private MockMvc mockMvc;
#Before
public void setUp(){
MockitoAnnotations.initMocks(this);
this.mockMvc = MockMvcBuilders.standaloneSetup(controller).build();
}
#Test
public void test() throws Exception{
mockMvc.perform(get("username")).andExpect(status().isOk());
}
}
And I get "404". Same thing if I test example "forwardedUrl("/PATH/login.jsp")" the result is null.
My Spring-Context.xml has
mvc:annotation-driven />
My console error is:
org.springframework.web.servlet.DispatcherServlet noHandlerFound
WARNING: No mapping found for HTTP request with URI [username] in DispatcherServlet with name ''
I don't really get that, because after all my application is working like it should so there is no problems with my mappings.

Related

Spring mvc unit test controller inject dao object using mockito

When using mockito to unit test Spring mvc controller, how to inject dao layer object. It's always giving null pointer exception with #Spy annotation when making use of SpringJUnit4ClassRunner class.
Sample code:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = { "classpath:**/evivecare-application-context-test.xml" })
#WithMockUser(username = "admin", roles={"ADMIN"})
#TestExecutionListeners({DependencyInjectionTestExecutionListener.class})
public class ControllerTest {
private MockMvc mockMvc;
#Mock
private SessionFactory sessionFactory;
#Mock
private Session session;
#InjectMocks
private FilterController filterController = new FilterController();
#Spy
private FilterService filterService= new FilterServiceImpl();
#Autowired
private FilterDAO filterDAO;
#Mock
private OperatorService userService;
#Mock
private EviveSpeechFilterService eviveSpeechFilterService;
private TestContextManager testContextManager;
#Before
public void setup() throws Exception {
// Process mock annotations
MockitoAnnotations.initMocks(this);
// Setup Spring test in standalone mode
this.mockMvc = MockMvcBuilders.standaloneSetup(filterController).build();
testContextManager = new TestContextManager(getClass());
testContextManager.prepareTestInstance(this);
filterDAO= new FilterDAOImpl(sessionFactory);
Mockito.doReturn(session).when(sessionFactory).getCurrentSession();
}
#Test
public void testController200() throws Exception{
Mockito.when(filterService.renameList("123","sdfgh")).thenReturn(false);
Mockito.when(filterDAO.renameList("123","sdfgh")).thenReturn(false);
this.mockMvc.perform(org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post("/renameList")
.sessionAttr("filterService", filterService)
.sessionAttr("filterDAO", filterDAO)
.param("listId", "1234567")
.param("alternateName", "LIst Name"))
.andExpect(org.springframework.test.web.servlet.result.MockMvcResultMatchers.status().isOk());
}
}
In this test case, the filterService in turn calls filterDAO, which is always returning null pointer exception.
So, what can I do to resolve this issue?
FilterService is not a managed bean, you probably need to inject the dao in the constructor since it won't be autowired inside filterService.
Please refer to this question on SO for more info: Support for autowiring in a class not instantiated by spring (3)

Spring MockMvc test: Null pointer Exception

I'm following tutorials for integrating Spring docs into my project but i'm running into nullpointerexception when I run my test.
The errors go away when I take out all the document bits. So when I remove restDocumentation variable, the document bit from the setup method and the test then it passes.
Here is my test class
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(loader = AnnotationConfigWebContextLoader.class, classes = { ContextConfiguration.class })
#WebAppConfiguration
public class ApiDocs {
#Rule
public RestDocumentation restDocumentation = new RestDocumentation(
"${project.basedir}/target/generated-snippets");
private RestDocumentationResultHandler document;
#Autowired
private WebApplicationContext context;
private MockMvc mockMvc;
#Autowired
Config Config;
#Before
public void setUp() {
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context)
.apply(documentationConfiguration(this.restDocumentation)).alwaysDo(this.document).build();
}
#Test
public void getConfig() throws Exception {
this.mockMvc.perform(get("/config").accept(MediaType.APPLICATION_JSON))
.andExpect(status().isOk()).andDo(document("index"));
}
}
The error that I'm getting(I've slashed out my class package due to privacy):
java.lang.NullPointerException
at org.springframework.test.web.servlet.MockMvc.applyDefualtResultActions(MockMvc.java:195)
at org.springframework.test.web.servlet.MockMvc.perform(MockMvc.java:163)
at //.//.//.//.//.ApiDocs.getConfig(ApiDocs.java:67)
at org.springframework.test.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
at org.springframework.test.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
at
org.springframework.restdocs.RestDocumentation$1.evaluate(RestDocumentation.java:59)
at org.springframework.test.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
at org.springframework.test.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:252)
at org.springframework.test.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94)
at org.springframework.test.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:75)
at org.springframework.test.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:75)
at org.springframework.test.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191)
Nothing's assigning a value to your this.document field so it's null. You're passing that into alwaysDo which then causes a NullPointerException.
You need to configure what you want to always happen. For example by adding this to the beginning of your setUp method:
this.document = document("{method-name}",
preprocessRequest(removeHeaders("Foo")),
preprocessResponse(prettyPrint()));
There's more information about this in the documentation.

How to write a mockito test case for ResourceAssembler with in Spring Hateos?

I am trying to write a unit test for the below Assembler but i keep getting Could not find current request via RequestContextHolder. Is this being called from a Spring MVC handler?. I wanted to know how i can mock out the resource creation?
#Component
public class LoginResourceAssembler extends ResourceAssemblerSupport<User, ResourceSupport> {
public LoginResourceAssembler() {
super(User.class, ResourceSupport.class);
}
#Override
public ResourceSupport toResource(User user) {
ResourceSupport resource = new ResourceSupport();
final String id = user.getId();
resource.add(linkTo(MyAccountsController.class).slash(id).slash("accounts").withRel("accounts"));
return resource;
}
}
Instead of changing from a plain unit test to a IMO integration test (given dependency of the spring framework) you could do something like:
#RunWith(MockitoJUnitRunner.class)
public class LoginResourceAssemblerTest {
#InjectMocks
private LoginResourceAssembler loginResourceAssembler;
#Before
public void setup() {
RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(new MockHttpServletRequest()));
}
#Test
public void testToResource() {
//...
}
}
I was seeing the error Could not find current request via RequestContextHolder. Is this being called from a Spring MVC handler because my test class was annotated with #RunWith(MockitoJUnitRunner.class) and this was not injecting the controller.
To fix this error, i annotated my test case with
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = Application.class)
#WebAppConfiguration
A working test case in my case
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = Application.class)
#WebAppConfiguration
public class LoginResourceAssemblerTest {
#Autowired
private WebApplicationContext context;
private MockMvc mockMvc;
#InjectMocks
private LoginResourceAssembler loginResourceAssembler;
#Before
public void setUp() {
initMocks(this);
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context).build();
}
#Test
public void testToResource() {
User user = new User();
user.setId("1234");
ResourceSupport resource = loginResourceAssembler.toResource(user);
assertEquals(1,resource.getLinks().size());
assertEquals("accounts",resource.getLinks().get(0).getRel());
assertTrue(resource.getLinks().get(0).getHref().contains("accounts"));
}
}

Spring MockMVC, Spring security and Mockito

I'd like to test a Spring Boot Rest controller, which is secured using Spring security, and use mocks inside it. I have tried with Mockito, but I think any mocking tool should do the trick.
To enable Spring security in my tests, I first did as follow:
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = Main.class)
#TestPropertySource(value="classpath:application-test.properties")
#WebAppConfiguration
#ContextConfiguration
public class MyTest{
protected MockMvc mockMvc;
#Autowired
private WebApplicationContext wac;
#Before
public void setUp(){
mockMvc = MockMvcBuilders
.webAppContextSetup(wac)
.apply(SecurityMockMvcConfigurers.springSecurity())
.build();
}
#Test
public void doTheTest(){
mockMvc.perform(post("/user/register")
.with(SecurityMockMvcRequestPostProcessors.csrf())
.content(someContent()));
}
}
Until there, it works well.
After this step, I wished to add mocks to test my secured controller in isolation.
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = Main.class)
#TestPropertySource(value="classpath:application-test.properties")
#WebAppConfiguration
#ContextConfiguration
public class MyTest{
protected MockMvc mockMvc;
#Mock
private Myservice serviceInjectedInController;
#InjectMocks
private MyController myController;
#Autowired
private WebApplicationContext wac;
#Before
public void setUp(){
mockMvc = MockMvcBuilders
.webAppContextSetup(wac)
.apply(SecurityMockMvcConfigurers.springSecurity())
.build();
}
#Test
public void doTheTest(){
mockMvc.perform(post("/user/register")
.with(SecurityMockMvcRequestPostProcessors.csrf())
.content(someContent()));
}
}
Unfortunately, the mocked service is not injected in the controller, as there is nothing relating the MockMVC and the Mocks, so the mocks are not injected in the controller.
So I tried changing the configuration of the MockMVC, as follows:
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = Main.class)
#TestPropertySource(value="classpath:application-test.properties")
#WebAppConfiguration
#ContextConfiguration
public class MyTest{
protected MockMvc mockMvc;
#Mock
private Myservice serviceInjectedInController;
#InjectMocks
private MyController myController;
#Before
public void setUp(){
mockMvc = MockMvcBuilders
.standAloneSetup(myController)
.apply(SecurityMockMvcConfigurers.springSecurity())
.build();
}
#Test
public void doTheTest(){
mockMvc.perform(post("/user/register")
.with(SecurityMockMvcRequestPostProcessors.csrf())
.content(someContent()));
}
}
But in this case, I have another issue. Spring security is complaining about the configuration:
java.lang.IllegalStateException: springSecurityFilterChain cannot be null. Ensure a Bean with the name springSecurityFilterChain implementing Filter is present or inject the Filter to be used.
I have no other idea to make security and mocking. Any idea? Or should I do another way?
Thanks.
By default the integration looks for a bean with the name of "springSecurityFilterChain". In the example that was provided, a standalone setup is being used which means MockMvc will not be aware of the WebApplicationContext provided within the test and thus not be able to look up the "springSecurityFilterChain" bean.
The easiest way to resolve this is to use something like this:
MockMvc mockMvc = MockMvcBuilders
// replace standaloneSetup with line below
.webAppContextSetup(wac)
.alwaysDo(print())
.apply(SecurityMockMvcConfigurers.springSecurity())
.build();
If you really want to use a standaloneSetup (doesn't really make sense since you already have a WebApplicationContext), you can explicitly provide the springSecurityFilterChain using:
#Autowired
FilterChainProxy springSecurityFilterChain;
#Before
public void startMocks(){
controller = wac.getBean(RecipesController.class);
MockMvc mockMvc = MockMvcBuilders
.standaloneSetup(controller)
.alwaysDo(print())
.apply(SecurityMockMvcConfigurers.springSecurity(springSecurityFilterChain))
.build();
MockitoAnnotations.initMocks(this);
}

Spring MVC test case

Am new to Spring MVC, i have written web servise using spring MVC and resteasy. My controller is working fine, now need to write testcase but i tried writtig but i never succed am also getting problem in autowiring.
#Controller
#Path("/searchapi")
public class SearchAPIController implements ISearchAPIController {
#Autowired
private ISearchAPIService srchapiservice;
#GET
#Path("/{domain}/{group}/search")
#Produces({"application/xml", "application/json"})
public Collections getSolrData(
#PathParam("domain") final String domain,
#PathParam("group") final String group,
#Context final UriInfo uriinfo) throws Exception {
System.out.println("LANDED IN get****************");
return srchapiservice.getData(domain, group, uriinfo);
}
}
can anyone give me sample code for Test case in spring mvc.
"Spring-MVC" Test case could seem like this using mock objects, for example we want to test my MyControllerToBeTest:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration("/spring.xml")
public class MyControllerTest {
private MockHttpServletRequest request;
private MockHttpServletResponse response;
private MyControllerToBeTested controller;
private AnnotationMethodHandlerAdapter adapter;
#Autowired
private ApplicationContext applicationContext;
#Before
public void setUp() {
request = new MockHttpServletRequest();
response = new MockHttpServletResponse();
response.setOutputStreamAccessAllowed(true);
controller = new MyControllerToBeTested();
adapter = new AnnotationMethodHandlerAdapter();
}
#Test
public void findRelatedVideosTest() throws Exception {
request.setRequestURI("/mypath");
request.setMethod("GET");
request.addParameter("myParam", "myValue");
adapter.handle(request, response, controller);
System.out.println(response.getContentAsString());
}
}
but i don't have any experience with REST resource testing, in your case RestEasy.
If you want to test the full service inside the container you can have a look at the REST Assured framework for Java. It makes it very easy to test and validate HTTP/REST-based services.

Resources