11

我开始使用 Spring 3.2 的新 MVC 测试框架,并为我的所有测试用例获取了 406 HTTP 响应代码。

测试用例很简单

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());
    }

}

对应的资源是

@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
    }

}

我确信这是因为媒体类型错误,但我不知道为什么。

失败的测试用例的痕迹:

java.lang.AssertionError: 预期状态:<200> 但在 org.springframework.test.util.AssertionErrors.fail(AssertionErrors.java:60) 处为 <406> 在 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) 在 de.yourdelivery.rest.location.LocationResouceTest.testGetLocationByPlzPattern(LocationResouceTest.java:37) 在 sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 在 sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) 在 sun .reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 在 java.lang.reflect.Method.invoke(Method.java:597) 在 org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15) 在 org.junit 的 org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:45)。 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) 在 org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74) 在 org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java: 83) 在 org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72) 在 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) 在 org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60) 在 org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229) 在 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 ) 在 org.junit 的 org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71)。org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:174) at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run( JUnit4TestReference.java:50) 在 org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) 在 org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:第 467 章.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)在 org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50) 在 org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.run(TestExecution.run) 运行(SpringJUnit4ClassRunner.java:174) java:38) 在 org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683) 在 org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)在 org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390) 在 org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)在 org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50) 在 org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.run(TestExecution.run) 运行(SpringJUnit4ClassRunner.java:174) java:38) 在 org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683) 在 org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)在 org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390) 在 org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467) 在 org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683) 在 org.eclipse.jdt.internal.junit。 runner.RemoteTestRunner.run(RemoteTestRunner.java:390) 在 org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467) 在 org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683) 在 org.eclipse.jdt.internal.junit。 runner.RemoteTestRunner.run(RemoteTestRunner.java:390) 在 org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)

4

8 回答 8

18

如果你有一个@Configuration类,你可以添加 @EnableWebMvc 注解而不是使用带有<mvc:annotation-driven />.

于 2013-11-18T19:00:12.180 回答
3

需要在spring xml中加入如下代码,在jackson中序列化POJO。

<annotation-driven />
于 2013-03-13T10:46:01.090 回答
3

这可能是由于 Spring 测试上下文中没有任何 MVC 配置造成的。使用类似的东西时:

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

...那么该test-context.xml文件还应包括以下内容:

<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>

使用没有指定任何特殊内容(例如: no producesin @RequestMapping)的控制器可以轻松测试上述问题是否存在,因此不需要任何内容​​协商:

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

...和:

@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"); 
}
于 2013-01-23T18:41:39.010 回答
3

必须同时拥有@EnableWebMvc.accept(MediaType.APPLICATION_JSON)

于 2016-09-01T20:32:30.903 回答
2

您缺少<mvc:annotation-driven />配置 xml 文件中的 。

于 2013-07-17T06:36:59.203 回答
0

我认为解决方法是这样修改请求:

this.mockMvc.perform(get("/someurl?someparam=somevalue").contentType(MediaType.APPLICATION_JSON)).andExpect..
于 2013-01-02T15:52:46.323 回答
0

我认为春天的做事方式是使用 HttpResponseEntity,或返回模型和视图。例如 :

@ResponseBody
ResponseEntity<String> getFoo() {
  HttpHeaders responseHeaders = new HttpHeaders();
  responseHeaders.setContentType(MediaType.APPLICATION_JSON);
  String test = "{\"foo\":{\"title\": \"Stack\"}}";
  return new ResponseEntity<String>(test, responseHeaders, HttpStatus.OK);
}

(我会对你取得的任何进一步进展感兴趣,因为它是全新的)

于 2013-01-02T14:56:12.340 回答
-1

我刚才也遇到了同样的问题,通过将Controller的返回类型改为String来解决。并直接返回 JSON 字符串而不是对象。它确实有效。

Gson gson = new Gson();
return gson.toJson(dto);
于 2013-04-11T06:35:13.377 回答