Fixtrue的释义是固定设备,指的是测试中被测试方法所依赖的数据和条件。在进行测试时,我们通常需要把环境设置成已知状态(如创建对象、获取资源等)来创建测试,每次测试开始时都处于一个固定的初始状态。测试前的状态被称为Test Fixture。
这样进行解释可能比较不好理解,我们还是直接上代码
示例:
假定我们有数据接口DBFactory,包含了2个方法find()、update()。我们要对这2个方法进行测试之前需要先初始化数据库连接
/**
* Created by zhangcs on 17-4-23.
*/
public class FixtrueExampleTest {
@Test
public void tesFind(){
// 初始化数据库连接
String driver = "com.mysql.jdbc.Driver";
String url = "jdbc:mysql://localhost:3306/samp_db";
String username = "root";
String password = "123456";
Class.forName( driver); //classLoader,加载对应驱动
Conection conn = (Connection) DriverManager.getConnection( url, username, password);
DBFactory dbFactory = new DBFactory( conn);
List< User> users = dbFactory.find( "张三");
assertNotNull( users);
// 关闭连接
conn.close();
}
@Test
public void testUpdate(){
// 初始化数据库连接
String driver = "com.mysql.jdbc.Driver";
String url = "jdbc:mysql://localhost:3306/samp_db";
String username = "root";
String password = "123456";
Class.forName( driver); //classLoader,加载对应驱动
Conection conn = (Connection) DriverManager.getConnection( url, username, password);
DBFactory dbFactory = new DBFactory( conn);
int result = dbFactory.update( "张三");
assertEquals( 1, result);
// 关闭连接
conn.close();
}
}
能够看得出来,初始化连接、关闭连接部分是重复的,大量重复代码的存在并不利于进行维护。而且在编写单元测试时,为了获得最好的结果,每一个测试方法都必须尽可能的简洁清晰和目的明确。基于这样的要求,我们就需要分离初始化逻辑、抽取公共逻辑,将初始化和关闭连接部分抽取出来。
我们对初始化连接和关闭连接的部分进行抽取:
/**
* Created by zhangcs on 17-4-23.
*/
public class FixtrueExampleTest {
private DBFactory dbFactory;
public void init(){
// 初始化数据库连接
String driver = "com.mysql.jdbc.Driver";
String url = "jdbc:mysql://localhost:3306/samp_db";
String username = "root";
String password = "123456";
Class.forName( driver); //classLoader,加载对应驱动
Conection conn = (Connection) DriverManager.getConnection( url, username, password);
dbFactory = new DBFactory( conn);
}
public void destroy(){
// 关闭连接
conn.close();
}
@Test
public void tesFind(){
// 初始化连接
inti();
List< User> users = dbFactory.find( "张三");
assertNotNull( users);
// 关闭连接
destroy();
}
@Test
public void testUpdate(){
// 初始化数据库连接
inti();
int result = dbFactory.update( "张三");
assertEquals( 1, result);
// 关闭连接
destroy();
}
}
仔细想想这似乎不对,我们其实只需要一次初始化和关闭操作。对于初始化,我们或许可以使用静态方法让它在类初始化时进行,但是关闭连接依旧麻烦。这只是一个较为简单的情况,而现实中的情况可能更为复杂。
为了应对这种情况,JUnit提供了可以在多个测试之间进行共享的fixture:
注解 | 说明 |
---|---|
@Before | 在每个@Test方法开始执行之前执行一次(存在多个测试方法时将会执行多次),被注解的方法必须是公有的 |
@After | 在每个@Test方法执行结束之后执行一次,其他与@Before类似 |
@BeforeClass | 在所有@Test方法开始执行之前执行一次(一共只会执行一次),被注解的方法必须是公有且静态的 |
@AfterClass | 在所有@Test方法执行结束之后执行一次,其他与@BeforeClass类似 |
使用@Before、@After、@BeforeClass、@AfterClass注解的方法不需要使用@Test,因为它们并非测试,而是fixture。需要注意的是,被@BeforeClass、@AfterClass注解的方法必须是公共且静态的
改进后的示例:
/**
* Created by zhangcs on 17-4-23.
*/
public class FixtrueExampleTest {
private static DBFactory dbFactory;
@BeforeClass
public static void init(){
// 初始化数据库连接
String driver = "com.mysql.jdbc.Driver";
String url = "jdbc:mysql://localhost:3306/samp_db";
String username = "root";
String password = "123456";
Class.forName( driver); //classLoader,加载对应驱动
Conection conn = (Connection) DriverManager.getConnection( url, username, password);
dbFactory = new DBFactory( conn);
}
@AfterClass
public static void destroy(){
// 关闭连接
conn.close();
}
@Test
public void tesFind(){
List< User> users = dbFactory.find( "张三");
assertNotNull( users);
}
@Test
public void testUpdate(){
int result = dbFactory.update( "张三");
assertEquals( 1, result);
}
}