由于课程实验要求做单元测试,所以就百度了很多文章,也基本了解了一些 JUnit 4的特性
@BeforeClass 在整个类加载之前,负责做配置
@Before 每个测试方法执行之前都会执行
@After 每个测试方法执行之后都会执行
@AfterCLass 在整个类加载之后,负责做 清理资源,
@Ignore 在测试类中并不是所有方法都是测试的,用Ignore 注解
@Test 要测试的方法
@BeforeClass
public static void setUpBeforeClass() throws Exception {
}
@AfterClass
public static void setUpAfterClass() throws Exception {
}
@Before
public void before() throws Exception {
}
@After
public void after() throws Exception {
}
@Test
public void add(){
}
包括JUnit 4 之前的测试类都要强制继承TestCase类,且测试方法名都要testXXX 之类的。
以及测试套件,是组织测试类一起运行的测试类。具体如下:
@RunWith(Suite.class) 1、更改测试运行器Suite.class。
@Suite.SuiteClasses({UserTest1,UserTest2,UserTest3}) 2。将需要运行的测试类放入Suite.SuiteClasses({})的数组中。
public class SuiteTest{} 3、更改测试运行器Suite.class。
百度很容易得到有明显输入输出的方法的测试,因为很简单,这里就不赘述了。我主要想讲的是比较复杂一点的情况。首先是 没有输入,没有输出的方法如何测试。
没有输入输出的方法,必定使类中的属性状态发生了改变,我们称之为副作用,如果没有这个副作用这个方法就是无用的。所以我么做测试的时候可以针对该方法中要改变的属性做检测,在运行该方法之前,记录属性状态,之后再做记录,对比下与方法逻辑对照,看更改的结果是否与想象中一致。 而对于私有方法,私有属性的测试就比较麻烦了。
例子:
package test.lifegame.demo;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import java.lang.reflect.Field;
import java.util.Timer;
import lifegame.demo.Time;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
/**
* Time Tester.
*
* @author
* @version 1.0
* @since <pre> 9.16, 2018</pre>
*/
public class TimeTest {
Time time;
Field startPressed;
Field timer;
@Before
public void before() throws Exception {
// 这个before函数 在测试方法之前执行,完成测试方法的基本配置
time = new Time();//分配内存
//用getClass().getDeclaredField("属性名")
//获得 time对象中的私有属性,这属于反射的内容
Field startPressed = time.getClass().getDeclaredField("startPressed");
startPressed.setAccessible(true);//突破 私有方法的访问权限,设置为true
Field timer = time.getClass().getDeclaredField("timer");
timer.setAccessible(true);
}
@After
public void after() throws Exception {
}
/**
* Method: start(int interval).
*/
@Test
public void testStart() throws Exception {
//TODO: Test goes here...
Timer t1 = (Timer) timer.get(time);//记录之前的状态
boolean s1 = (boolean) startPressed.get(time);
assertFalse(s1);//在运行start之前 是 false
assertNull(t1);// start运行之前null
time.start(1000);
boolean s2 = (boolean) startPressed.get(time);//记录之后的状态
Timer t2 = (Timer) timer.get(time);
assertTrue(s2);
assertNotNull(t2);
}
/**
* Method: stop().
*/
@Test
public void testStop() throws Exception {
//TODO: Test goes here...
Timer t1 = (Timer) timer.get(time);
boolean s1 = (boolean) startPressed.get(time);
assertTrue(s1);//stop之前是true
assertNotNull(t1);// stop运行之前 不是Null
time.stop();
boolean s2 = (boolean) startPressed.get(time);
Timer t2 = (Timer) timer.get(time);
assertFalse(s2);
assertNull(t2);
}
/**
* Method: addActionListener().
*/
@Test
public void testAddActionListener() throws Exception {
//TODO: Test goes here...
// 对事件绑定的测试
}
/**
* Method: run().
*/
@Test
public void testRun() throws Exception {
//TODO: Test goes here...
//对UI的测试
}
}
而对于运行的方法,需要配置的对象依赖比较多的时候,可以使用 mock 方法进行模拟,
@Before
public void before() throws Exception {
map = new Map();
map.setCols(30);
map.setRows(30);
map.setRatio(0.3);
map.init_maps();
view = new View(30, 30, 0.3);
logic = new Logic(view, map);
//这里是对logic这个类的配置,依赖只有两个类,也已经很麻烦了
//所以Mock 大有市场,还有一种运用mock的场景是代替没写完的模块来做测试
//具体的Mock我还没试过,就留着后面再写了。
}