Spring MVC 返回 406 到控制器测试

Posted

技术标签:

【中文标题】Spring MVC 返回 406 到控制器测试【英文标题】:Spring MVC returning 406 to controller test 【发布时间】:2018-04-27 22:12:33 【问题描述】:

我有以下项目树:

├── app
│   ├── build.gradle
│   └── src
│       ├── main
│       │   ├── java
│       │   │   └── child
│       │   │       └── app
│       │   │           └── Application.java
│       │   └── resources
│       │       └── application-default.yaml
│       └── test
│           └── java
│               └── child
│                   └── app
│                       └── ApplicationTest.java
├── build.gradle
└── childA
    ├── build.gradle
    └── src
        ├── main
        │   └── java
        │       └── child
        │           └── a
        │               ├── CoreConfig.java
        │               ├── PingController.java
        │               └── SpringWebMvcInitializer.java
        └── test
            └── java
            │   └── child
            │       └── a
            │           └── PingControllerTest.java
            └── resources
                └── application-core.yml

我有以下测试类:

@RunWith(SpringRunner.class)
@ContextConfiguration(classes =  PingController.class, SpringWebMvcInitializer.class , initializers = ConfigFileApplicationContextInitializer.class)
@WebAppConfiguration
@ActiveProfiles( "core" )
public class PingControllerTest 

    private MockMvc mockMvc;

    @Autowired
    private WebApplicationContext webApplicationContext;

    @Before
    public void setUp() 
        mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
    

    @Test
    public void testPing() throws Exception 
this.mockMvc.perform(get(CoreHttpPathStore.PING)).andDo(print());
this.mockMvc.perform(get(CoreHttpPathStore.PING).accept(MediaType.APPLICATION_JSON_UTF8_VALUE).contentType(MediaType.APPLICATION_JSON_UTF8_VALUE)).andExpect(status().isOk());
    


我有以下PingController.java

@RestController
public class PingController 

    @RequestMapping(value = CoreHttpPathStore.PING, method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public ResponseEntity<Map<String, Object>> ping() throws Exception 
        HashMap<String, Object> map = new HashMap<>();
        map.put("message", "Welcome to our API");
        map.put("date", new Date());
        map.put("status", HttpStatus.OK);
        return new ResponseEntity<>(map, HttpStatus.OK);
    


我有以下SpringWebMvcInitializer.java

@ComponentScan
public class SpringWebMvcInitializer extends AbstractAnnotationConfigDispatcherServletInitializer 

    @Override
    protected Class<?>[] getRootConfigClasses() 
        return new Class<?>[];
    

    @Override
    protected Class<?>[] getServletConfigClasses() 
        return new Class<?>[];
    

    @Override
    protected String[] getServletMappings() 
        return new String[] "/" ;
    


预期

我希望测试通过 http 代码200

结果

我得到406 和以下print()

04:29:47.488 [main] DEBUG org.springframework.test.web.servlet.TestDispatcherServlet - Successfully completed request

MockHttpServletRequest:
      HTTP Method = GET
      Request URI = /ping
       Parameters = 
          Headers = 

Handler:
             Type = com.kopaxgroup.api.core.controller.PingController

Async:
    Async started = false
     Async result = null

Resolved Exception:
             Type = org.springframework.web.HttpMediaTypeNotAcceptableException

ModelAndView:
        View name = null
             View = null
            Model = null

FlashMap:
       Attributes = null

MockHttpServletResponse:
           Status = 406
    Error message = null
          Headers = 
     Content type = null
             Body = 
    Forwarded URL = null
   Redirected URL = null
          Cookies = []

问题

所以这是我的问题:

我做了一些谷歌搜索,大多数答案都说上下文需要用@ContextConfiguration("/test-context.xml") 加载,我使用 JAVA 配置并且我没有 XML。我的SpringWebMvcInitializer.java 是否替换了该文件,它是否正确替换了它?

为什么会出现 406 错误?

【问题讨论】:

【参考方案1】:

我认为最简单的方法是创建TestApplication 类并将其放入/childA/test/java/a

import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class TestApplication 

如果你使用 Spring Boot,我认为最好使用以下注解进行测试:

@RunWith(SpringRunner.class)
@SpringBootTest
@ActiveProfiles("core")
public class PingControllerTest 
...

【讨论】:

我有很多子项目childBchildC ...那么移动TestApplication的目标是什么? 我的意思是为每个子项目新建一个TestApplication类,放到子项目的层次上(/childA/test/java/a/TestAplication.java, /childB/test /java/b/TestAplication.java)。这个类应该只有注解@SpringBootApplication。 我已经尝试过了,这将返回一个 404 错误代码。似乎@SpringBootApplication 需要在测试中以某种方式导入?我尝试使用@ContextConfiguration 导入它,但由于数据源配置不正确,它也开始发出呜呜声。我试图用@ComponentScan("my.package") 注释TestApplication 并没有改善任何东西。【参考方案2】:

您可以尝试添加内容类型。 this.mockMvc.perform(get(CoreHttpPathStore.PING).accept(MediaType.APPLICATION_JSON)).contentType(MediaType.APPLICATION_JSON))andExpect(status().isOk());

【讨论】:

谢谢,我试过你的例子,它也返回406【参考方案3】:

尝试执行以下步骤:

@Configuration
    @EnableWebMvc
    public static class PingControllerTestConfiguration 

        @Bean
        public PingController myController() 
            return new PingController();
        
    

下面改

@ContextConfiguration(classes =  PingController.class, SpringWebMvcInitializer.class , initializers = ConfigFileApplicationContextInitializer.class)

@ContextConfiguration

【讨论】:

这是用于调试目的的测试吗?我应该在哪里创建那个新文件,为什么要为我的每个控制器都这样做? 您将在 PingControllerTest 类中执行此操作,PingControllerTestConfiguration 类是 PingControllerTest 类中的内部类,用于实例化控制器以进行测试 这项工作,但为什么我需要写这个?这不是文档描述的内容。此外,这也适用于安全控制器和 spring-securityspring-security-oauth 吗?如果我需要加载我的配置怎么办(例如,如果控制器是 @Auowiring MailService 我没有用spring security试过这个,你可以试试测试一下。 EnableWebMvc 注解支持使用@RequestMapping 将传入请求映射到特定方法的@Controller-注解类。在 Test 类中,它的工作方式与 Java 注释 spring 上下文的任何 AppConfig 类相同。 我已经尝试过,但它在我的大多数情况下都不起作用。我需要能够在控制器中自动装配。这适用于大多数简单的情况。

以上是关于Spring MVC 返回 406 到控制器测试的主要内容,如果未能解决你的问题,请参考以下文章

Spring MVC 测试框架因 HTTP 响应 406 而失败

spring mvc 不返回 json 内容 - 错误 406

mvc:annotation-driven 不能解决 406 错误

Spring MVC - 将对象返回为@ResponseBody 时出现问题(著名的错误 406,未解决)

SSM框架整合时ajax请求返回406

spring3.1.1正常的在spring 4.1.2 配置 jackson 返回406 如何解决