11

I am trying to write test cases for controller. I do not want to mock out my service as I would like to use these tests as complete functionality tests.

I am trying to test this controller:

@Controller
public class PlanController {

     @Autowired
     private PlanService planService;

     @RequestMapping(
        value = "/api/plans/{planId}",
        method = RequestMethod.GET,
        produces = MediaType.APPLICATION_JSON_VALUE)
     @ResponseBody
     @Nonnull
     @JsonView(Plan.SimpleView.class)
     public Plan getPlan(@RequestParam int orgId, @PathVariable int planId) {
         Plan plan = planService.getPlan(orgId, planId);
         return plan;
    }
}

and Here is test case I have written:

package com.videology.skunkworks.audiencediscovery.controller;

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

import org.eclipse.jetty.webapp.WebAppContext;  
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.MockitoAnnotations;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {WebAppContext.class})
@WebAppConfiguration
@EnableWebMvc
public class PlanControllerTest {

    @Autowired
    private WebApplicationContext wac;

    private MockMvc mockMvc;

    @Before
    public void setup() {
        MockitoAnnotations.initMocks(this);
        this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).dispatchOptions(true).build();
    }

    @Test
    public void testGetPlan() throws Exception {
        mockMvc.perform(get("/api/plans/1/?orgId=1").accept(MediaType.APPLICATION_JSON_VALUE)).andExpect(status().isOk());
    }
}

This test case is failing because status() being returned is 404 not 200. Not sure why it is returning 404 as errorMessage is null.

I have been through many similar questions but None of them were helpful for me.

Gaurav Kumar Singh
  • 582
  • 2
  • 5
  • 14

6 Answers6

10

Error was in configuration. To Fix this, I had to provide my WebConfig file in contextConfiguration. Here is line I added:

@ContextConfiguration(classes = {WebConfig.class})
Gaurav Kumar Singh
  • 582
  • 2
  • 5
  • 14
  • The same for me except I use `AbstractAnnotationConfigDispatcherServletInitializer` to initialise web configuration, so needed to add app configuration as well as web configuration to `@ContextConfiguration` – Krzysztof Skrzynecki Jul 24 '19 at 10:15
5

Maybe it depends on the version. I had to add @Import(MyController.class). The result:

@WebMvcTest(controllers = MyController.class)
@Import(MyController.class)
@ContextConfiguration(classes = {MyConfig.class})
class MyControllerTest {
}
2

I had to use the standaloneSetup. You may want to try that. I also had to add a viewResolver. My code looks something like this.

I'm using SpringBoot 1.5.

@RunWith(SpringRunner.class)
@ContextConfiguration(classes = {
    FilterChainProxy.class,
    HomeController.class
})
@WebAppConfiguration
public class HelloWorldTest {

    @Autowired
    private WebApplicationContext context;

    @Autowired
    private FilterChainProxy springSecurityFilterChain;

    private MockMvc mvc;


    @Before
    public void setup() {
        InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
        viewResolver.setPrefix("/templates/");
        viewResolver.setSuffix(".ftl");

        mvc = MockMvcBuilders
                .standaloneSetup(new HomeController())
                .setViewResolvers(viewResolver)
                .alwaysDo(print())
                .build();
    }


    @Test
    public void test() throws Exception {
        MvcResult result = mvc.perform(get("/home")
                .with(anonymous()))
                .andExpect(status().is2xxSuccessful())
                .andReturn();

        assertEquals("home", result.getModelAndView().getViewName());
    }
}
Tony Zampogna
  • 1,928
  • 1
  • 12
  • 14
2

I am running Spring Boot 2.5.6, doing test for my controller. Had many difficulties, as Spring wanted to load few security related beans. Finally, managed to run the controller test with something like below:

@WebMvcTest(controllers = AuthenticationController.class,
        excludeAutoConfiguration = SecurityAutoConfiguration.class, // turn off websecurity (authorisation)
        useDefaultFilters = false
)
@Import(AuthenticationController.class)
Yazid
  • 409
  • 7
  • 8
0

Your @EnableWebMvc may not configured, Check it in your classpath is there any class contains annotation:

@EnableWebMvc
-1

Add class annotation - @WebMvcTest(PlanController.class) It works for me.