SpringMVC的 Mockmvc的优势:
所谓的Mock测试,就像servletAPI中的HttpServletRequest对象是Tomcat容器生成的。我们无法手动的new出来,于是就有了所谓的Mock测试
对模块进行集成测试时,希望能够通过输入URL对Controller进行测试,如果通过启动服务器,建立http client进行测试,这样会使得测试变得很麻烦,比如启动速度慢,测试验证不方便,依赖网络环境等,这样会导致测试无法进行,为了可以对Controller进行测试,可以通过引入MockMVC进行解决。
pom.xml 依赖
<!-- spring-test -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring-framework.version}</version>
<scope>test</scope>
</dependency>
<!-- junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
常用的注释:
@RunWith(SpringJUnit4ClassRunner.class)
使用Spring-Test框架, 在使用所有注释前必须使用 @RunWithSpringJUnit4ClassRunner.class),让spring test 运行于Spring测试环境, 通俗的理解就是指定测试类使用某个运行器.
@WebAppConfiguration
使用这个注释会在执行单元测试的时候真实的启动一个web服务,然后开始调用Controller的Rest API,待单元测试执行完后再将web服务停止.
@ContextConfiguration
指定需要加载的spring配置文件的地址, 可以有多种方式. 如果有多个配置文件,可以用括号括起来,controller,component等都是使用注解,需要注解指定spring的配置文件,扫描相应的配置,将类初始化等。
@TransactionConfiguration(transactionManager="transactionManager",defaultRollback=true)
配置事务的回滚 ,对数据库的增删改都会回滚,便于测试用例的循环利用
@Transactional
非必须,是和@TestExecutionListeners中的TransactionalTestExecutionListener.class配合使用,用于保证插入的数据库中的测试数据,在测试完后,事务回滚,将插入的数据删除,保证数据库的干净。如果没有显示的指定@Transactional,那么插入到数据库中的数据就是真实数据。
@Mock
MockMvc模拟MVC对象,通过MockMvcBuilders.webAppContextSetup(this.wac).build()进行初始化
@InjectMocks
需要将Mock对象注入的对象, 可以是被测的Controller
@Before
在每个Test方法之前运行的方法,一般用来初始化方法
mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
@Test
执行测试
@Autowired
为Spring提供的注解,需要导入包org.springframework.beans.factory.annotation.Autowired;按照类型(byType)注入.默认情况下它要求依赖对象必须存在
@After
在每个测试方法后执行,在方法执行完成后要做的事情
实际运用:
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.transaction.TransactionConfiguration;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.context.WebApplicationContext;
//这个必须使用junit4.9以上才有
@RunWith(SpringJUnit4ClassRunner.class)
//单元测试的时候真实的开启一个web服务
@WebAppConfiguration
//配置事务的回滚,对数据库的增删改都会回滚,便于测试用例的循环利用
@TransactionConfiguration(transactionManager="transactionManager",defaultRollback=true)
@Transactional
//指定需要加载的spring配置文件的地址, 可以有多种方式. 如果有多个配置文件
@ContextConfiguration(locations = {"classpath:spring.xml","classpath:spring-hibernate.xml"})
public class ControllerTest {
MockMvc mockMvc;
@Autowired //spring 自动注入
WebApplicationContext wac;
@Autowired
MyWebConfig myWebConfig=new MyWebConfig();
@Before //每次Test方法之前运行的方法,常用于初始化操作
public void setUp(){
System.out.println("----------Before----------");
DefaultMockMvcBuilder builder = MockMvcBuilders.webAppContextSetup(this.wac);
//mockMvc= MockMvcBuilders.standaloneSetup(myWebConfig).build();
mockMvc = builder.build();
}
@Test
public void testUserController() throws Exception {
this.mockMvc.perform(get("/deviceevent/list") //
.accept(MediaType.parseMediaType("text/html;charset=UTF-8")))
.andExpect(status().isOk()) // 验证status code
.andExpect(model().size(1)) //
}
@After
public void testAfter(){
System.out.println("-----------After-------------- ");
}
}
为什么要做事务回滚?
在写单元测试的时候,一般是对数据库进行增删改查的操作,这个时候,如果之前删除了某条记录,自然后面的程序就找不到这条记录,所以可以通过配置spring的事务管理或者测试框架来回滚,减少工作量,同时也保证每一次测试的数据都是干净的。
测试是保证软件质量的关键, mock是为了测试Web项目不需要启动web server等服务项目,我们只需要一些Servlet相关的模拟对象,比如:MockMVC,MockHttpServletRequest,MockHttpServletResponse,MockHttpSession等。在Spring里,我们使用@WebAppConfiguration指定加载的ApplicationContext是一个WebAppConfiguration即可对某一模块进行单独测试.