测试SpringMVC中controller,demo项目采用spring boot方式搭建,依赖使用maven。
pom.xml
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.0.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!--jsp依赖-->
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<version>3.11.1</version>
<scope>test</scope>
</dependency>
</dependencies>
application.properties
# 页面默认前缀目录
spring.mvc.view.prefix=/WEB-INF/jsp/
# 响应页面默认后缀
spring.mvc.view.suffix=.jsp
server.port=8080
测试controller
package com.example.demo;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
/**
* @author Walker
* @since 1.0 2018-09-30
*/
@Controller
public class TestController {
@RequestMapping(value = {"/", "/index"})
public String index(Map<String, Object> model) {
model.put("time", new Date());
return "index";
}
@RequestMapping("/test")
@ResponseBody
public String test() {
return "ok";
}
@RequestMapping("/upload")
@ResponseBody
public String upload(@RequestParam("file") MultipartFile file) throws IOException {
System.out.println(IOUtils.toString(file.getInputStream(), "utf-8"));
return file.getName();
}
}
测试用例,使用TestRestTemplate访问首页:
package com.example.demo;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.test.context.junit4.SpringRunner;
import static org.assertj.core.api.Assertions.assertThat;
/**
* @author Walker
* @since 1.0 2018-09-30
*/
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class HttpRequestTest {
@LocalServerPort
private int port;
@Autowired
private TestRestTemplate restTemplate;
@Test
public void testController() {
String result = restTemplate.getForObject("http://localhost:" + port + "/", String.class);
System.out.println(result);
assertThat(result).contains("Time");
}
}
结果:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Spring Boot Sample</title>
</head>
<body>
Time: Sun Sep 30 15:12:30 CST 2018
</body>
</html>
如果只想测试web层,可以使用@WebMvcTest注解,其参数可指定加载的controller类,如果此时controller类依赖其他bean,如service等,可使用 @MockBean注入bean,否则应用启动报错。
第二个测试用例,使用@WebMvcTest
package com.example.demo;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import static org.hamcrest.core.StringContains.containsString;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
/**
* 仅加载web层
* @author Walker
* @since 1.0 2018-09-30
*/
@RunWith(SpringRunner.class)
@WebMvcTest(/*TestController.class*/)
public class WebLayerTest {
@Autowired
private MockMvc mockMvc;
@MockBean
private AsyncTask task;
@Test
public void test() throws Exception {
mockMvc.perform(get("/test")).andDo(print())
.andExpect(status().isOk())
.andExpect(content().string(containsString("ok")));
//当这个方法被调用时,设置方法返回值
when(task.test()).thenReturn("hello");
mockMvc.perform(get("/testReturn")).andDo(print())
.andExpect(status().isOk())
.andExpect(content().string(containsString("hello")));
}
@Test
public void test2() throws Exception {
mockMvc.perform(get("/page1")).andDo(print())
.andExpect(forwardedUrl("/WEB-INF/jsp/page/page1.jsp")).andReturn();
}
}
test()输出结果:
MockHttpServletRequest:
HTTP Method = GET
Request URI = /test
Parameters = {}
Headers = {}
Body = <no character encoding set>
Session Attrs = {}
Handler:
Type = com.example.demo.TestController
Method = public java.lang.String com.example.demo.TestController.test()
Async:
Async started = false
Async result = null
Resolved Exception:
Type = null
ModelAndView:
View name = null
View = null
Model = null
FlashMap:
Attributes = null
MockHttpServletResponse:
Status = 200
Error message = null
Headers = {Content-Type=[text/plain;charset=UTF-8], Content-Length=[2]}
Content type = text/plain;charset=UTF-8
Body = ok
Forwarded URL = null
Redirected URL = null
Cookies = []
MockHttpServletRequest:
HTTP Method = GET
Request URI = /testReturn
Parameters = {}
Headers = {}
Body = <no character encoding set>
Session Attrs = {}
Handler:
Type = com.example.demo.PageController
Method = public java.lang.String com.example.demo.PageController.testReturn()
Async:
Async started = false
Async result = null
Resolved Exception:
Type = null
ModelAndView:
View name = null
View = null
Model = null
FlashMap:
Attributes = null
MockHttpServletResponse:
Status = 200
Error message = null
Headers = {Content-Type=[text/plain;charset=UTF-8], Content-Length=[5]}
Content type = text/plain;charset=UTF-8
Body = hello
Forwarded URL = null
Redirected URL = null
Cookies = []
test2()输出结果:
MockHttpServletRequest:
HTTP Method = GET
Request URI = /page1
Parameters = {}
Headers = {}
Body = <no character encoding set>
Session Attrs = {}
Handler:
Type = com.example.demo.PageController
Method = public org.springframework.web.servlet.ModelAndView com.example.demo.PageController.page1()
Async:
Async started = false
Async result = null
Resolved Exception:
Type = null
ModelAndView:
View name = page/page1
View = null
Attribute = content
value = Hello Shanhy
FlashMap:
Attributes = null
MockHttpServletResponse:
Status = 200
Error message = null
Headers = {Content-Language=[en]}
Content type = null
Body =
Forwarded URL = /WEB-INF/jsp/page/page1.jsp
Redirected URL = null
Cookies = []
再看看如何测试上传文件:
@Test
public void upload() throws Exception {
MockMultipartFile file = new MockMultipartFile("file", "test.txt", "text/plain", "filecontent".getBytes());
mockMvc.perform(multipart("/upload").file(file))
.andDo(print())
.andExpect(status().isOk());
}
测试结果:
MockHttpServletRequest:
HTTP Method = POST
Request URI = /upload
Parameters = {}
Headers = {Content-Type=[multipart/form-data]}
Body = <no character encoding set>
Session Attrs = {}
Handler:
Type = com.example.demo.TestController
Method = public java.lang.String com.example.demo.TestController.upload(org.springframework.web.multipart.MultipartFile) throws java.io.IOException
Async:
Async started = false
Async result = null
Resolved Exception:
Type = null
ModelAndView:
View name = null
View = null
Model = null
FlashMap:
Attributes = null
MockHttpServletResponse:
Status = 200
Error message = null
Headers = {Content-Type=[text/plain;charset=UTF-8], Content-Length=[4]}
Content type = text/plain;charset=UTF-8
Body = file
Forwarded URL = null
Redirected URL = null
Cookies = []