单元测试基本概念
- SUT:被测系统
- Test Double:测试替身,具体有
Dummy Object
,Test Stub
,Mock Object
等 - Test Fixture:测试皮具,就是测试运行程序会再测试方法之前自动初始化,回收资源的工作。
- Test Suite:测试套件,解决每次只能运行一个测试用例的情况,可以批量运行。
- Assertions:断言,是测试框架里面的若干个方法,用来判断某个语句的结果是否为真或判断是否与预期相符。
JUnit4
JUnit4与之前的版本有了很多的改变,主要是使用了Java中的Annotation
和静态导入,变得更加地好用了。
package cn.qingtianr.dao;
import org.junit.*;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
/**
* Created by jack on 16-7-3.
*/
public class ThemeMapperTest {
@BeforeClass
public static void setUpClass() throws Exception{
}
@AfterClass
public static void tearDownClass() throws Exception{
}
@Before
public void setUp() throws Exception {
}
@After
public void tearDown() throws Exception {
}
@Test(expected = NullPointerException.class)//判断是否抛出空指针异常
public void testShowAllTheme() throws Exception {
}
@Test(timeout = 10)//判断是否执行时间再10秒之内
public void testFindThemeById() throws Exception {
}
@Test
public void testFindThemeReplys() throws Exception {
assertEquals(1,1);
assertThat(55, greaterThan(50));//判断55是否大于50
}
}
再JUnit4中使用@Test
注解即可对任意函数签名指定为测试函数。然后JUnit4中还提供了@BeforeClass
来初始化一些昂贵的资源比如数据库链接,使用@Before
来初始化准备环境。BeforeClass
只会初始化一次,但是@Before
每一次测试函数运行之前都会运行一次。同理AfterClass
和After
。
当然JUnit4还有一些高级功能。比如参数化测试,打包测试。有必要的话,以后在列出例子。
除了JUnit4测试框架之外,还有模拟对象用的Mockito框架,Unitils框架,数据库测试框架Dbunit。
JUnit4有了Spring测试框架支持后的DAO测试
因为是对DAO层的测试,所以要再Service层调用DAO层代码进行测试。
没有Spring测试框架之前
package service;
import static org.Junit.Assert.assertEquals;
import org.Junit.BeforeClass;
import org.Junit.Test;
import org.Springframework.context.ApplicationContext;
import org.Springframework.context.support.ClassPathXmlApplicationContext;
import domain.Account;
public class AccountServiceOldTest {
private static AccountService service;
@BeforeClass
public static void init() {
ApplicationContext
context = new ClassPathXmlApplicationContext("config/Spring-db-old.xml");
service = (AccountService)context.getBean("accountService");
}
@Test
public void testGetAcccountById() {
Account acct = Account.getAccount(1, "user01", 18, "M");
Account acct2 = null;
try {
service.insertIfNotExist(acct);
acct2 = service.getAccountById(1);
assertEquals(acct, acct2);
} catch (Exception ex) {
fail(ex.getMessage());
} finally {
service.removeAccount(acct);
}
}
}
有了Spring测试框架之后
package service;
import static org.Junit.Assert.assertEquals;
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.Junit4.SpringJUnit4ClassRunner;
import org.Springframework.transaction.annotation.Transactional;
import domain.Account;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("/config/Spring-db1.xml")
@Transactional
public class AccountServiceTest1 {
@Autowired
private AccountService service;
@Test
public void testGetAcccountById() {
Account acct = Account.getAccount(1, "user01", 18, "M");
service.insertIfNotExist(acct);
Account acct2 = service.getAccountById(1);
assertEquals(acct,acct2);
}
}
通过例子可以看出来,Spring测试框架主要解决下面几件事情。
- 不用手动导入Spring的配置文件,可以使用注解进行
- 不同手动
getBean
得到Bean对象,Bean对象可以使用@Autowired
来进行自动注入 - 不用调用完DAO层代码,然后撤销操作影响,Spring测试框架直接事务回滚。
当然为了使用到Spring测试框架的功能,主要要使用到如下几点的东西。
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("/config/Spring-db1.xml")
- 在Spring的配置文件中配置事务管理器
- @Transactional
JUnit有了Spring之后的Controller层测试(带补充)
JUnit没有Spring之前的测试
JUnit有了Spring之后的测试
以上是使用原始的Spring项目架构的测试过程,但是如果使用了SpringBoot的话,还是会有一些不一样的地方的。下面来讲一下如果使用了SpringBoot的话,项目会又哪一些改变。
参考:
- 使用 Spring 进行单元测试
- 15. Integration Testing
- 完成了单元测试,你的测试之旅才刚上路
- Spring MVC Controller 单元测试
- 使用Spring配合Junit进行单元测试的总结
- Spring Boot Junit单元测试