在Spring Boot应用中做单元测试
在Spring Boot应用中做单元测试
文中用的Spring Boot是1.5.4版。
1. 添加Maven依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
按理来说只要添加上述依赖就好了。但如果你跟我一样,在跑测试时各种报错ClassNotFoundException net.minidev.xxx,请在pom文件中再加上如下两个依赖。
<dependency>
<groupId>net.minidev</groupId>
<artifactId>json-smart</artifactId>
<version>2.2.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>net.minidev</groupId>
<artifactId>asm</artifactId>
<version>1.0.2</version>
<scope>test</scope>
</dependency>
遇到ClassNotFoundException 之类的问题,可参考我之前写的博客,一般不是因为所需的库重复,就是因为库不存在。可用mvn dependency:tree
查看项目中库的依赖关系(直接在pom文件所在目录运行该命令就行了)。
2. 测试Service
@RunWith(SpringRunner.class)
@SpringBootTest
public class StudentTest {
@Autowired
private StudentService studentService;
@Test
public void likeName() {
assertArrayEquals(
new Object[]{
studentService.likeName("小明2").size() > 0,
studentService.likeName("坏").size() > 0,
studentService.likeName("莉莉").size() > 0
},
new Object[]{
true,
false,
true
}
);
}
}
第一个注解 @RunWith(SpringRunner.class)
告诉Junit运行使用Spring的测试支持,将运行spring的全部流程,再启动单元测试,也就是说会类似于spring的正常启动启动服务。
在JUnit中有很多个Runner,他们负责调用你的测试代码。如果只是普通的Java测试,该注解可省略,系统会自动使用默认Runner来运行你的测试类。
值得注意的是,网上很多教程用的是SpringJUnit4ClassRunner
这个类,但这个类在1.5版本的Spring Boot已经被废弃了(1.4版本能用),不建议使用。
第二个注解@SpringBootTest
表示使用带有Spring Boot支持的引导程序。该注解能在运行时配置Spring Boot的环境。
还可以用注解@ContextConfiguration(locations = "classpath:spring.xml")
指定要加载的Spring配置文件,此处spring.xml文件放在了test的resource文件夹中。
网上有不少教程用的是@SpringApplicationConfiguration
这个注解,该注解在1.4版的Spring Boot就被标记为过时了。
像平常测试一样,测试方法用
@Test
注解标注,测试类中也可以使用@Autowired
来注入要测试的类的实例(因为测试环境是真实的Spring上下文)。在最新版的JUnit中,assertEquals这类方法已经被废弃了,建议使用assertArrayEquals,可一次性输入多组测试数据。
2. 测试Controller
有两种方式,一是使用RestTemplate对象执行http请求,二是mock一个MVC环境。
其中注解@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
表示使用带有Spring Boot支持的引导程序,并使用默认的端口。该选项主要是为了在单元测试中通过 TestRestTemplate
对象模拟 http请求。
第一种:
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class TestExample2 {
@LocalServerPort
private int port;
private URL base;
@Autowired
private TestRestTemplate template;
@Before
public void setUp() throws Exception {
this.base = new URL("http://localhost:" + port + "/getUser/1");
}
@Test
public void getHello() throws Exception {
User user = userMapper.getById(1L);
ResponseEntity<String> response = template.getForEntity(base.toString(),
String.class);
assertThat(response.getStatusCode, is(HttpStatus.OK))
assertThat(response.getBody(), equalTo(user.toString()));
}
}
第二种:
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@AutoConfigureMockMvc
public class TestExample {
@Autowired
private MockMvc mvc;
@Autowired
private UserMapper userMapper;
@Test
public void testGetById() throws Exception {
User user = userMapper.getById(1L);
String uri = "/getUser/1";
MvcResult mvcResult = mvc.perform(MockMvcRequestBuilders.get(uri).accept(MediaType.APPLICATION_JSON))
.andReturn();
int status = mvcResult.getResponse().getStatus();
String content = mvcResult.getResponse().getContentAsString();
assertTrue("错误,正确的返回值为200", status == 200);
assertFalse("数据不一致", !user.toString().equals(content));
}
}
- 点赞
- 收藏
- 关注作者
评论(0)