Spring MVC testframework fails with HTTP Response 406

12,047

Solution 1

If you have a @Configuration class, you can add the @EnableWebMvc annotation instead of using an XML configuration with <mvc:annotation-driven />.

Solution 2

This might be caused by not having any MVC configuration in the Spring test context. When using something like:

@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration("/test-context.xml")

...then that test-context.xml file should also include things like:

<mvc:annotation-driven content-negotiation-manager="contentNegotiationManager">
  <mvc:message-converters>
    <bean id="..." class=
"org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"/>
    <bean id="..."
      class="org.springframework.http.converter.StringHttpMessageConverter"/>
    <bean id="..."
      class="org.springframework.http.converter.FormHttpMessageConverter"/>
  </mvc:message-converters>
</mvc:annotation-driven>

<bean id="contentNegotiationManager" 
  class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
  <property name="defaultContentType" value="application/json" />
  <property name="mediaTypes">
    <value>
      json=application/json
      xml=application/xml
    </value>
  </property>
</bean>

One can easily test if the above is the problem, with a controller that does not specify anything special (such as: no produces in @RequestMapping), and hence does not need any content negotiation:

@RequestMapping(value = "/foo", method = RequestMethod.GET)
@ResponseBody
public String getFoo() {
    return "bar";
}

...with:

@Test
public void getFoo() throws Exception {
    MvcResult result = 
      this.mockMvc.perform(get("/foo").accept(MediaType.TEXT_PLAIN))
        .andExpect(status().isOk())
        .andReturn();
    Assert.assertEquals(result.getResponse().getContentAsString(), "bar"); 
}

Solution 3

You need to add the following code to spring xml to serialize POJO in jackson.

<annotation-driven />

Solution 4

It is necessary to have both @EnableWebMvc and .accept(MediaType.APPLICATION_JSON)

Solution 5

You are missing the <mvc:annotation-driven /> in the configuration xml file.

Share:
12,047
MatthiasLaug
Author by

MatthiasLaug

Updated on June 03, 2022

Comments

  • MatthiasLaug
    MatthiasLaug about 2 years

    I started to use the new MVC Testframework of Spring 3.2 and got stuck with getting 406 HTTP Response Codes for all my test cases.

    The testcase is plain simple

    public class LocationResouceTest {
    
        @Autowired
        private WebApplicationContext wac;
    
        private MockMvc mockMvc;
    
        @Before
        public void setup() {
            this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
        }
    
        @Test
        public void testGetLocationByPlzPattern() throws Exception {
            // here I need to define the media type as a static var from MediaType
            this.mockMvc.perform(get("/someurl?someparam=somevalue")).andExpect(status().isOk());
        }
    
    }
    

    the corresponding resource is

    @Controller
    // here I need to define the media type as string
    @RequestMapping(value = "/someurl", produces = "application/json; charset=UTF-8")
    public class LocationResource {
    
        @ResponseBody
        @RequestMapping(method = RequestMethod.GET)
        public ArrayList<DTO> getAllIndex(@RequestParam("someparam") String param) {
            return ... //the list of DTO classes is transformed to json just fine if called with curl
        }
    
    }
    

    I am sure it is because of a wrong media type but I cannot figure out why.

    The trace of the failing testcase:

    java.lang.AssertionError: Status expected:<200> but was:<406> at org.springframework.test.util.AssertionErrors.fail(AssertionErrors.java:60) at org.springframework.test.util.AssertionErrors.assertEquals(AssertionErrors.java:89) at org.springframework.test.web.servlet.result.StatusResultMatchers$5.match(StatusResultMatchers.java:546) at org.springframework.test.web.servlet.MockMvc$1.andExpect(MockMvc.java:141) at de.yourdelivery.rest.location.LocationResouceTest.testGetLocationByPlzPattern(LocationResouceTest.java:37) 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.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28) 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.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:88) 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)

  • MatthiasLaug
    MatthiasLaug over 11 years
    ok I checked that and still get a 406 response. I altered my question to have the accept method removed
  • MatthiasLaug
    MatthiasLaug over 11 years
    tried that as well. The result is the same with ?someparam and param("someparam", value)
  • MatthiasLaug
    MatthiasLaug over 11 years
    I do not get a response at all but a 406, so no json... but still works if I curl it
  • Raedwald
    Raedwald almost 11 years
    Spring should be outputting many error messages if that was the case, no?
  • Arjan
    Arjan almost 11 years
    I don't think so, @Raedwald. I posted this after running into 406 Unacceptable myself, and then having found the fix. Not sure if I got any stack traces then, but I doubt it. During initialisation, I don't see why Spring would print any errors for the @RequestMapping when not knowing yet what requests it would ever get. And during an actual request it would simply not be able to map it; not much errors to print there? Not being able to map the actual request would be the same as requesting an unknown URL, or requesting using an unmapped HTTP method: an HTTP error response without much else?
  • Kyleinincubator
    Kyleinincubator about 10 years
    I got the same issue and tried the way provided in this thread. But still 406.
  • dragn
    dragn over 9 years
    Thank you. This fixed my issue.
  • Erin Drummond
    Erin Drummond over 9 years
    Thanks, adding @EnableWebMvc to my Test @Configuration class did the trick!
  • Carlos Verdes
    Carlos Verdes about 9 years
    Thanks, finally I found my problem!!
  • LoBo
    LoBo over 3 years
    Appropriate namespace is xmlns:mvc="springframework.org/schema/mvc".