Fork me on GitHub

SpringMVC学习4-单元测试

Spring MVC

SpringMVC是基于MVC思想的JAVA WEB实现框架,是Spring家族的一员,它基于前置控制器来接收并分发请求,支持参考验证、请求参数封装、拦截、Restful等功能,是目前较为流行的MVC框架

本系列学习笔记包含如下的课程内容:

  • MVC思想
  • Hello案例
  • 请求和响应处理
  • 文件上传和下载处理
  • 参数验证
  • 请求拦截
  • RESTful风格
  • 日志

TestNG

TestNG is a testing framework inspired from JUnit and NUnit but introducing some new functionalities that make it more powerful and easier to use, such as:

  • Annotations.
  • Run your tests in arbitrarily big thread pools with various policies available (all methods in their own thread, one thread per test class, etc…).
  • Test that your code is multithread safe.
  • Flexible test configuration.
  • Support for data-driven testing (with @DataProvider).
  • Support for parameters.
  • Powerful execution model (no more TestSuite).
  • Supported by a variety of tools and plug-ins (Eclipse, IDEA, Maven, etc…).
  • Embeds BeanShell for further flexibility.
  • Default JDK functions for runtime and logging (no dependencies).
  • Dependent methods for application server testing.

pom.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>6.8.8</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>2.2.9</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-core</artifactId>
<version>1.2.1</version>
<scope>test</scope>
</dependency>

service 单元测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.testng.AbstractTestNGSpringContextTests;
import org.testng.Assert;
import org.testng.annotations.Test;

/**
* ServiceConfig 单元测试类
*/
@Test
@ContextConfiguration(classes = ServiceConfig.class) //使用了 ServiceConfig 类
public class ServiceConfigTest extends AbstractTestNGSpringContextTests {

@Autowired
private HelloService helloService;

public void test1() {
String actual = helloService.sayHi("jack");
Assert.assertEquals(actual, "Hello, jack");
}

}

控制器 单元测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
import com.tz.WebMvcConfig;
import org.mockito.MockitoAnnotations;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.testng.AbstractTestNGSpringContextTests;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.web.context.WebApplicationContext;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.model;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view;
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.webAppContextSetup;

/**
* Created by steven
*/
@Test
@ContextConfiguration(classes = WebMvcConfig.class)
@WebAppConfiguration //初始化 WebApplicationContext 实例
public class HelloControllerTest extends AbstractTestNGSpringContextTests {

@Autowired
private WebApplicationContext wac; //web spring 容器实例

private MockMvc mockMvc; //控制器单元测试入口

/**
* 初始化 web 测试环境
*/
@BeforeClass
public void setup() {
MockitoAnnotations.initMocks(this);
mockMvc = webAppContextSetup(wac).build();
}

public void testHello() throws Exception {
mockMvc.perform(get("/hello?name=jack"))
.andExpect(status().isOk()) //Http 状态码 200
.andExpect(view().name("/WEB-INF/jsp/hello.jsp")) //返回的 jsp 视图名
.andExpect(model().attribute("result", "Hello, jack")); //模型数据细节
}

}

Run

mvn test -Dtest=ServiceConfigTest -Dgroups=g1
or
mvn test -Dtest=ServiceConfigTest -Dgroups=g1,g2

断言异常

1
2
3
4
@Test(expectedExceptions = SomeException.class)
public void test1() {
//...
}

控制执行顺序

priority

1
2
3
4
5
6
7
8
@Test(priority=1)
public void test1() {}

@Test(priority=2)
public void test2() {}

@Test(priority=3)
public void test3() {}

dependsOn

In TestNG, you use dependsOnMethods and/or dependsOnGroups:

1
2
3
4
5
6
7
8
@Test(groups = "a")
public void f1() {}

@Test(groups = "a")
public void f2() {}

@Test(dependsOnGroups = "a")
public void g() {}

or

1
2
3
4
5
6
7
8
@Test
public void Test1() {}

@Test (dependsOnMethods={"Test1"})
public void Test2() {}

@Test (dependsOnMethods={"Test2"})
public void Test3() {}