spring4 test 测试框架使用
spring作为最负盛名的java框架,自然有配套的测试框架,这就是Spring Test框架。spring测试框架整合junit,jmock等单元测试框架,为开发人员节省了大量时间。Spring测试框架还包括springMVC的 web测试,引入springMVC测试框架后,应用无需在j2ee容器中启动即可断言调试,并且支持事物回滚。
添加依赖
在spring项目中,首先需要加入Spring Test框架依赖。下面是gradle配置依赖的写法。
dependencies {
testCompile group: 'junit', name: 'junit', version: '4.12'
testCompile 'org.springframework:spring-test:4.1.7.RELEASE'
}
集成单元测试
为了重用代码,通常写一个基类来配置测试环境,代码如下:
package com.chenkaihua.test.unit;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.transaction.TransactionConfiguration;
import org.springframework.transaction.annotation.Transactional;
/**
* Created by chenkaihua on 15-11-27.
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:spring-config.xml")
@TransactionConfiguration(transactionManager = "transactionManager",defaultRollback = true)
@Transactional
public class BaseUnitTest {
@Test
public void test(){
}
}
下面解释下主要注解:
@RunWith: 用于指定junit运行环境,是junit提供给其他框架测试环境接口扩展,spring
为了便于使用spring的依赖注入,spring提供了org.springframework.test.context.junit4.SpringJUnit4ClassRunner作为junit测试环境。@ContextConfiguration:用于指定spring配置环境。@TransactionConfiguration:用于配置事物。@Transactional:表示所有类下所有方法都使用事物。
编写单元测试
个人认为,单元测试到service级别最好,我通常是一个service配套一个单元测试,下面是一个简单的测试,使用了spring注入
package com.chenkaihua.test.unit;
import com.dreamliner.mhml.entity.User;
import com.dreamliner.mhml.mapper.ImageResourceMapper;
import com.dreamliner.mhml.service.UserService;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import static org.junit.Assert.*;
/**
* Created by chenkaihua on 15-11-27.
*/
public class UserServiceTest extends BaseUnitTest {
@Autowired
UserService userService;
@Autowired
ImageResourceMapper imageResourceMapper;
@Test
public void testLogin() throws Exception{
User selectUser = new User();
selectUser.setPhone("1111111111");
selectUser.setPassword("pass");
User user = userService.selectWithAvatar(selectUser);
assertNotNull(user);
assertNotNull(user.getAvatar());
}
}
可以看到,UserServiceTest继承单元测试基类BaseUnitTest,由于BaseUnitTest配置了测试环境,因此这里可以直接使用spring注入注解,是不是方便了很多!
集成MVC测试
首先,也是编写一个基类,用于配置测试环境
package com.chenkaihua.test.web;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.ContextHierarchy;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.transaction.TransactionConfiguration;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.context.WebApplicationContext;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.webAppContextSetup;
/**
* Created by chenkaihua on 15-10-29.
*/
@WebAppConfiguration
@Transactional(value = "transactionManager")
@TransactionConfiguration(defaultRollback = true,transactionManager = "transactionManager")
@RunWith(SpringJUnit4ClassRunner.class)
@ContextHierarchy({
@ContextConfiguration("classpath:spring-config.xml"),
@ContextConfiguration("classpath:spring-mvc-config.xml")
})
public class WebBaseTest {
@Autowired
protected WebApplicationContext wac;
protected MockMvc mockMvc;
@Before
public void setup() {
this.mockMvc = webAppContextSetup(this.wac).build();
}
@Test
public void test() throws Exception {
}
}
有几个注意的地方
@WebAppConfiguration:指定是mvc测试环境ContextHierarchy:指定spring配置文件层次结构,即spring-mvc-config.xml上下文继承pring-config.xml,也就是把springMVC环境配置文件加入进来。WebApplicationContext:模拟的webapp context。MockMvc:一个模拟的MVC环境。
编写mvc测试用例
在web测试中,主要是基于Controller写的web接口测试。
package com.chenkaihua.test.web;
import com.dreamliner.mhml.service.UserService;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mock.web.MockMultipartFile;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.fileUpload;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
/**
* Created by chenkaihua on 15-12-12.
*/
public class UserControllerTest extends WebBaseTest {
@Autowired
UserService userService;
@Test
public void testRegister() throws Exception {
mockMvc.perform(post("/users").param("phone", "11111111111").param("password", "passssss")).andDo(print())
.andExpect(status().isOk()).andReturn();
}
}
这是个测试注册的方法,被测试UserController代码如下:
@RequestMapping(method = RequestMethod.POST)
public ResponseEntity register(@RequestParam String phone, @RequestParam String password) {
boolean register = userService.isRegister(phone);
if (register) {
return ResponseEntity.status(Status.STATUS_1).body("user has register");
}
User user = new User();
user.setPhone(phone);
user.setName("user" + phone.substring(0,2)+"******"+phone.substring(phone.length()-3,phone.length()-1));
user.setPassword(password);
userService.insert(user);
return ResponseEntity.ok(user);
}
mockMvc.perform(): 用于构造一个测试请求,即模拟一个request。可以指定HTTP方法(POST,GET,DELETE,PUT等),路径,参数等。andDo(print()): 请求完后,打印结果。运行测试时,会在控制台打印请求详情,已经被调用的Controller的具体信息。andExpect(status().isOk()):请求完后的断言,判断返回的状态码是否为200
文件上传测试
web开发中,文件上传是基本功能。spring mvc测试框架中可以很方便的测试文件上传
@Test
public void testUploadAvatar() throws Exception {
MockMultipartFile mockMultipartFile = new MockMultipartFile("avatarFile", "testsssssss".getBytes());
mockMvc.perform(fileUpload("/users/1/avatar").
file(mockMultipartFile).param("type", "img"))
.andDo(print()).andExpect(status().isOk()).andReturn();
}
MockMultipartFile:模拟一个文件出出来,可以传byte[]构造fileUpload():以post方式提交multipart request
mvc测试非常强大,还可以设定session等。总之,request的所有属性都可以模拟。