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
...
【讨论】:
我有很多子项目childB
,childC
...那么移动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-security
和 spring-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 错误