一,基础注解
junit的基础注解有@BeforeClass,Before,Test(),After,@AfterClass
执行顺序为:@BeforeClass>Before>Test1>After>Before>Test2>After>AfterClass
具体用法看一下代码:
public class Demo1Test {
/**
* BeforeClass注解的方法,应当为静态(static)的,且该方法在测试中只会执行一次,在第一个测试方法(即在第一个被test注解的方法)之前运行。
* 常用于执行计算代价很大的任务,如打开数据库连接
*/
@BeforeClass
public static void connect() {
System.out.println("数据库连接");
}
/**
* 被before注解的方法会在每一个测试方法(被test()注解的方法)运行前执行一次。
* 常用于初始化测试方法的资源。
*/
@Before
public void testInit() {
System.out.println("初始化test");
}
/**
* 被test注解的方法为要测试的代码。其中有俩个参数:1.expected 表示此测试方法执行后应该抛出的异常;2。timeout 检测测试方法的执行时间。
* test中应当有使用断言来判断代码是否成功。
*/
@Test(expected = ArithmeticException.class)
public void test1() {
//判断第一个参数(预期结果)是否与第二个参数(实际结果)相等。
//若断言为假则会爆出expected的值ArithmeticException(算数异常)
System.out.println("执行单元测试2");
assertEquals(1, 2);
}
/**
* timeout的单位为毫秒,测试方法中休眠俩秒,导致测试方法的执行时间大于1.1秒,因此会爆出异常(TestTimedOutException)。
*
*/
@Test(timeout = 1100)
public void test2() {
try {
//休眠俩秒
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException ie) {
Thread.currentThread().interrupt();
}
System.out.println("执行单元测试2");
}
/**
* 该类型的方法被用来关闭由@Before注解修饰的测试方法打开的资源。
*/
@After
public void closetest() {
System.out.println("closstest");
}
/**
* 该方法也是只会执行一次,且只会在最后一个测试方法执行完之后执行。同时该方法也应当为静态方法。
* 该类型的方法被用来关闭由@BeforeClass注解修饰的测试方法打开的资源,如关闭数据库连接。
*/
@AfterClass
public static void close() {
System.out.println("close");
}
}
用例执行结果
![](https://i-blog.csdnimg.cn/blog_migrate/79d30280c4833a2b9ed9424900239427.png)
test1方法中断言结果为假,爆出算数错误
![](https://i-blog.csdnimg.cn/blog_migrate/ac77ffa03f3f03bdc81930a3d2814812.png)
test2中运行时间超过1.1秒,导致出现“”超时“”错误。
![](https://i-blog.csdnimg.cn/blog_migrate/adfea6a9b2131dd324fa933fd5445a88.png)
二、junit断言
1.junit4 assert断言
1.1.1例子如下
public class AssertTest {
/**
* assertEquals(Object expected, Object actual)检查俩个参数是否相等,可以检查基础数据类型和引用数据类型等。expected为预期的,actual为实际的。
*/
@Test
public void testAssertEquals() {
Demo1 d1 = new Demo1(1, 1);
Demo1 d2 = new Demo1(1, 1);
//检查两个引用数据类型是否相等时,通过检查俩个对象的地址来判断是否为同一个对象。同理,判断数组和集合时,应当也是通过检查地址来判断是否相等。
// assertEquals(d1, d1);
// assertEquals("asd", "asd");
int [] a = {1,2,3};
int [] b = {1,2,3};
assertEquals(a, a);
// assertEquals(2, 1);
}
/**
* assertTrue(boolean condition)检查条件为真,condition翻译为:条件
*/
@Test
public void testAssertTrue() {
assertTrue(2 > 1);
}
/**
* assertFalse(boolean condition)检查条件为假,condition翻译为:条件
*/
@Test
public void testAssertFalse() {
assertFalse(2 > 1);
}
/**
* assertNotNull(Object object)检查对象不为空
*/
@Test
public void testAssertNotNull() {
assertNotNull(new String());
}
/**
* assertNull(Object object)检查对象为空
*/
@Test
public void testAssertNull() {
assertNull(new String());
}
/**
* 检查俩个对象是否不指向同一个对象,即俩个对象的引用地址不同,也可以判断基本数据类型是否不相等
*/
@Test
public void testAssertNotSame() {
Demo1 d1 = new Demo1(1, 1);
Demo1 d2 = new Demo1(1, 1);
assertNotSame(d1, d2);
// assertNotSame("string", "String");
}
/**
* 检查俩个对象是否指向同一个对象,即俩个对象的引用地址相同,也可以判断基本数据类型是否相等。
*/
@Test
public void testAssertSame() {
Demo1 d1 = new Demo1(1, 1);
Demo1 d2 = new Demo1(1, 1);
assertSame(d1, d2);
// assertSame(1, 1);
}
/**
* assertArrayEquals(Object[] expecteds, Object[] actuals)检查两个数组是否相等
* 该方法与assertEquls的区别在于,assertEquls是根据俩个数组的引用地址来检查,而assertArrayEquals则会对数组中每一个元素的值进行判断
*/
@Test
public void testAssertArrayEquals() {
int[] a = {1,2,3};
int[] b = {1,2,3};
int[] c = {1,2,2};
//该方法会爆出错误,错误中的预期和实际结果都为16进制数字
// assertEquals(a, b);
//该方法不会爆出错误
assertArrayEquals(a,b);
//该方法爆出错误,因为俩个数组中最后一个元素的值不同。具体可以运行查看错误信息。
// assertArrayEquals(a,c);
}
}
1.1.2方法汇总
方法名称 | 作用 |
assertEquals(Object expected, Object actual) | 检查俩个参数是否相等 |
assertTrue(boolean condition) | 检查条件为真 |
assertFalse(boolean condition) | 检查条件为假 |
assertNotNull(Object object) | 检查对象不为空 |
assertNull(Object object) | 检查对象为空 |
assertNotSame(Object unexpected, Object actual) | 检查俩个对象是否不指向同一个对象 |
assertSame(Object expected, Object actual) | 检查俩个对象是否指向同一个对象 |
assertArrayEquals(Object[] expecteds, Object[] actuals) | 检查两个数组是否相等 |
2.junit4 assertThat断言
![](https://i-blog.csdnimg.cn/blog_migrate/4eac46d073e2d92e4ee3c2022750c58f.png)
这是我所用的jar包版本
不知道是我自己的原因还是这个jar包的原因,要是想用assertThat断言需要在文件顶部导入方法。
![](https://i-blog.csdnimg.cn/blog_migrate/da07d4e1c606155f38a88ba147573da5.png)
而要是用*号的话也是导入不了的。
![](https://i-blog.csdnimg.cn/blog_migrate/255e3cf2ce5d152a3056ffd6db85995f.png)
![](https://i-blog.csdnimg.cn/blog_migrate/46c9ce70172e6635b6b359b8be5cdef4.png)
我们可以先看一下assertThat方法的形参。
![](https://i-blog.csdnimg.cn/blog_migrate/0f80f4c2076a32d79281f871d44dfe43.png)
第一个参数为Object类型,参数名为actual,可知,第一个参数为实际结果,而第二个参数为预期结果,这和assertEquls断言是不一样的。
第二个参数为Matcher类型的,Matcher译为匹配符,匹配符有一般匹配符,字符串相关匹配符,集合相关匹配符,数值相关匹配符这四种类型。其中泛型所定义的<? super Object>理解为只接受Object类型和Object类的父类。
要注意的是这里的Object是根据你所传入的数据类型来变换的
![](https://i-blog.csdnimg.cn/blog_migrate/d954843bff25a0b35973be76d1a64677.png)
如我这里传入进去的为"mysql",方法中的形参类型也由Object变成String。
2.1一般匹配符断言
2.1.1具体例子如下:
//一般匹配符
public class GeneralMatches {
/**
* allOf(Matcher<? super String> first, Matcher<? super String> second)表示,第一个参数(实际结果)必须满足allOf中所有的条件。
* 由上面可以看出,allOf方法中的形参类型为匹配符(Mather).且该匹配符方法的形参类型应当为String类型或String类型的父类。
*/
@Test
public void testAllof() {
assertThat("mysql", allOf(startsWith("my"),containsString("sq")));
}
/**
* anyOf(Matcher<String> first, Matcher<? super String> second)表示,第一个参数(实际结果)必须满足allOf中所有的条件。
* 由上面可以看出,anyOf方法中的形参类型为匹配符(Mather).且该匹配符方法的形参类型应当为String类型或String类型的父类。
*/
@Test
public void testAnyOf() {
assertThat("mysql", anyOf(startsWith("my"),containsString("sq1")));
}
/**
* anything()表示,无论什么条件,永远为true。
*/
@Test
public void testAnything() {
assertThat("mysql", anything());
}
/**
* is(String value)表示,前面的实际结果与后面的预期结果相等.
* 实际结果指的的assertThat方法中的第一个参数,预期结果指的的is中的参数。
*/
@Test
public void testIs() {
assertThat("mysql", is("mysql"));
}
/**
* not(String value)表示,前面的实际结果与后面的预期结果不等.
* 实际结果指的的assertThat方法中的第一个参数,预期结果指的的is中的参数。
*/
@Test
public void testNot() {
assertThat("mysql", not("123"));
}
/**
* both()表示,预期结果满足both中的条件和每一个and中的条件或任意一个or中的条件
*/
@Test
public void testBoth() {
assertThat("mysql", both(containsString("my")).and(containsString("s1")).and(containsString("ql")).or(containsString("ql")));
}
/**
* 值不为空
*/
@Test
public void testNotNullValue() {
String str2 = "123";
assertThat(str2, is(notNullValue()));
}
/**
* 值为空
*/
@Test
public void testNullValue() {
String str2 = "123";
assertThat(str2, is(nullValue()));
}
}
2.1.2方法汇总
方法名称 | 作用 |
allOf(Matcher<? super String> first, Matcher<? super String> second) | 表示,第一个参数(实际结果)必须满足allOf中所有的条件。 |
anyOf(Matcher<String> first, Matcher<? super String> second) | 表示,第一个参数(实际结果)必须满足allOf中所有的条件。 |
anything() | 表示,无论什么条件,永远为true |
is(String value) | 表示,前面的实际结果与后面的预期结果相等. |
not(String value) | 表示,前面的实际结果与后面的预期结果不等. |
both(Matcher<String> first) | 表示,预期结果满足both中的条件和每一个and中的条件或任意一个or中的条件 |
notNullValue() | 值不为空 |
nullValue() | 值为空 |
2.2.junit4 字符串相关匹配符
2.2.1具体例子如下
//字符串相关匹配符
public class StringMatches {
/**
* containsString(String substring)表示,前面的字符串(实际结果)中包字符串substring。
*/
@Test
public void testContainsString() {
assertThat("hello-java", containsString("-"));
}
/**
* endsWith(String suffix)表示,前面的字符串(实际结果)中以字符串suffix结尾。
*/
@Test
public void testEndsWith() {
assertThat("hello-java", endsWith("va"));
}
/**
* startsWith(String prefix)表示,前面的字符串(实际结果)中以字符串prefix开头。
*/
@Test
public void testStartsWith() {
assertThat("hello-java", startsWith("he"));
}
/**
* equalTo(String operand)表示,检查前面的实际结果与operand相等则通过,可以用于字符串之间或对象之间。
*/
@Test
public void testEqualTo() {
assertThat("hello-java", equalTo("hello-java"));
}
/**
* equalToIgnoringCase(String expectedString)表示,前面的实际结果(字符串)在忽略大小写的情况下与expectedString相等则通过.。
*/
@Test
public void testEqualToIgnoringCase() {
assertThat("hello-java", equalToIgnoringCase("HELLO-java"));
}
/**
* equalToIgnoringWhiteSpace(String expectedString)表示,前面的实际结果(字符串)在忽略头尾任意个空格的情况下与expectedString相等则通过.。
*/
@Test
public void testEqualToIgnoringWhiteSpace() {
assertThat("hello-java", equalToIgnoringWhiteSpace(" hello-java"));
}
}
2.2.2方法汇总
方法名称 | 作用 |
containsString(String substring) | 前面的字符串(实际结果)中包字符串substring。 |
endsWith(String suffix) | 表示,前面的字符串(实际结果)中以字符串suffix结尾。 |
startsWith(String prefix)。 | 表示,前面的字符串(实际结果)中以字符串prefix开头 |
equalTo(String operand) | 表示,检查前面的实际结果与operand相等则通过,可以用于字符串之间或对象之间。 |
equalToIgnoringCase(String expectedString) | 表示,前面的实际结果(字符串)在忽略大小写的情况下与expectedString相等则通过.。 |
equalToIgnoringWhiteSpace(String expectedString) | 表示,前面的实际结果(字符串)在忽略头尾任意个空格的情况下与expectedString相等则通过。 |
2.3数值相关匹配符
2.3.1具体例子
//数值相关匹配符
public class NumMatches {
/*
* closeTo(double operand, double error)。
* operand译为操作数,error译为误差,该方法的作用为,实际结果在{operand-error,poerand+error}区间则测试通过。注意,该区间为开区间。
*/
@Test
public void testCloseTo() {
assertThat(0.971, is(closeTo(1.0, 0.03)));
}
/*
* greaterThan(Integer value),当实际结果大于value时(不包括等于),则测试通过
*/
@Test
public void testGreaterThan() {
assertThat(2, is(greaterThan(1)));
}
/*
* lessThan(Integer value),当实际结果小于value时(不包括等于),则测试通过
*/
@Test
public void testLessThan() {
assertThat(1, is(lessThan(0)));
}
/*
* greaterThanOrEqualTo(Double value),当实际结果大于等于value时,则测试通过
*/
@Test
public void testGreaterThanOrEqualTo() {
assertThat(1.03, is(greaterThanOrEqualTo(1.0)));
}
/*
* lessThanOrEqualTo(Double value),当实际结果小于等于value时,则测试通过
*/
@Test
public void testLessThanOrEqualTo() {
assertThat(1.0, is(lessThanOrEqualTo(1.0)));
}
}
2.3.2方法汇总
方法名 | 作用 |
closeTo(double operand, double error) | 实际结果在{operand-error,poerand+error}区间则测试通过。注意,该区间为开区间。 |
greaterThan(Integer value) | 当实际结果大于value时(不包括等于),则测试通过 |
lessThan(Integer value) | 当实际结果小于value时(不包括等于),则测试通过 |
greaterThanOrEqualTo(Double value) | 当实际结果大于等于value时,则测试通过 |
lessThanOrEqualTo(Double value) | 当实际结果小于等于value时,则测试通过 |
2.4集合相关匹配符
2.4.1具体例子
//集合相关匹配符
public class ArraysMatchers {
// 以下为List集合相关匹配符。
/*
* everyItem(Matcher<String> itemMatcher)
* 实际结果的集合中,每一项都要满足itemMatcher的条件,即如下例子所示,集合中每一项都要以m开头,测试才通过。
*/
@Test
public void testEveryItem() {
assertThat(Arrays.asList("my", "asList"), everyItem(startsWith("m")));
}
/*
* hasItem(String item) 实际结果的集合中,包含item这个元素,即如下例子所示,集合中要有一个元素为123,测试才通过。
*/
@Test
public void testHasItem() {
List<String> l = new ArrayList();
l.add("123");
l.add("asd");
l.add("123");
// assertThat(Arrays.asList("my","asList"),hasItem("my"));
assertThat(l, hasItem("123"));
}
/*
* hasItems(String... items),该方法中使用了...符号,代表该方法形参的个数是可变的,但是类型必须为String类型。
* 该方法表示:在实际结果的集合中,集合要包含多个元素,即如下例子所示,集合中要有元素为123和asd,测试才通过。
*/
@Test
public void testHasItems() {
List<String> l = new ArrayList();
l.add("123");
l.add("asd");
assertThat(l, hasItems("123", "asd"));
}
/*
* isIn(Collection<String> collection)该方法表示,实际结果与collection集合中的一个元素相等,则测试通过。
*/
@Test
public void testIsIn() {
List<String> l = new ArrayList();
l.add("123");
l.add("asd");
assertThat("123", isIn(l));
}
/*
* empty()表示实际结果(集合)为空集合。
*/
@Test
public void testEmpty() {
List<String> l = new ArrayList();
assertThat(l, empty());
}
/*
* hasSize(int size)表示实际结果(集合)的长度为size。
*/
@Test
public void testHasSize() {
List<String> l = new ArrayList();
l.add("123");
assertThat(l, hasSize(1));
}
// 以下的匹配符与map集合相关。
/*
* hasEntry(String key, String value),map集合中包含特定的键(key)值(value)对。
*/
@Test
public void testHasEntry() {
Map<String, String> m = new HashMap<String, String>() {
{
put("1", "励志名言");
put("2", "爱情名言");
}
};
assertThat(m, hasEntry("2", "爱情名言"));
}
/*
* hasKey(String key),map集合中包含特定的键(key)。
*/
@Test
public void testHasKey() {
Map<String, String> m = new HashMap<String, String>() {
{
put("1", "励志名言");
put("2", "爱情名言");
}
};
assertThat(m, hasKey("2"));
}
/*
* hasValue(String value),map集合中包含特定的值(value)。
*/
@Test
public void testHasValue() {
Map<String, String> m = new HashMap<String, String>() {
{
put("1", "励志名言");
put("2", "爱情名言");
}
};
assertThat(m, hasValue("爱情名言"));
}
// 以下为数组相关匹配符
@SuppressWarnings("unchecked")
/*
* array(Matcher<? super Integer>... elementMatchers)该方法中的形参个数是可变的。
* 用处:实际结果中数组长度相等且对应元素也相等
*/
@Test
public void testArray() {
Integer[] a = { 1, 2, 3, 4 };
assertThat(a, is(array(equalTo(1), equalTo(2), equalTo(3), equalTo(4))));
}
/*
* hasItemInArray(Integer element)数组是否包含元素element
*/
@Test
public void testHasItemInArray() {
Integer[] a = { 1, 2, 3, 4 };
assertThat(a, hasItemInArray(1));
}
/*
* arrayContainingInAnyOrder(Integer... items)忽略顺序,长度相等以及数组元素中的值都有
*/
@Test
public void testArrayContainingInAnyOrder() {
Integer[] a = { 1, 2, 3, 4 };
assertThat(a, arrayContainingInAnyOrder(1, 3, 2, 4));
}
/*
* arrayContaining(Integer... items),要顺序,长度以及元素都一致。
*/
@Test
public void testArrayContaining() {
Integer[] a = { 1, 2, 3, 4 };
assertThat(a, arrayContaining(1, 2, 3, 4));
}
}
2.4.2方法汇总
everyItem(Matcher<String> itemMatcher) | 实际结果的集合中,每一项都要满足itemMatcher的条件 |
hasItem(String item) | 实际结果的集合中,包含item这个元素 |
hasItems(String... items) | 在实际结果的集合中,集合要包含多个元素 |
isIn(Collection<String> collection) | 实际结果与collection集合中的一个元素相等,则测试通过 |
empty() | 表示实际结果(集合)为空集合 |
hasSize(int size) | 表示实际结果(集合)的长度为size |
hasEntry(String key, String value) | map集合中包含特定的键(key)值(value)对。 |
hasKey(String key) | map集合中包含特定的键(key)。 |
hasValue(String value) | map集合中包含特定的值(value)。 |
array(Matcher<? super Integer>... elementMatchers) | 实际结果中数组长度相等且对应元素也相等 |
hasItemInArray(Integer element) | 数组是否包含元素element |
arrayContainingInAnyOrder(Integer... items) | 忽略顺序,长度相等以及数组元素中的值都有 |
arrayContaining(Integer... items) | 要顺序,长度以及元素都一致。 |
三、junit参数化
例子如下:
//1.使用@RunWith(Parameterized.class)注释测试类。
@RunWith(Parameterized.class)
public class ParameterTest {
//2.声明测试数据变量。
private String parameter;//被测方法需要传入的参数
private String expect;//预期结果
//3.创建构造函数,用于初始化测试数据。
public ParameterTest(String parameter, String expect) {
super();
this.parameter = parameter;
this.expect = expect;
}
//4.创建一个使用@Parameters注释的公共静态方法,该方法返回一个二维集合作为测试数据集。其中每一行都为一组测试数据。
@Parameters
public static Collection<Object[]> Data() {
return Arrays.asList(new Object[][] {
{"李华","欢迎您:李华"},
{"李四","欢迎您:李四"},
{"王五","欢迎您:王五"},
});
}
//5.使用上面定义的变量作为测试数据进行测试。
@Test
public void test() {
String result = Demo1.t1(parameter);
System.out.println("parameter:" + parameter + ";" + "expect:" + expect);
assertEquals(expect, result);
}
}
运行结果如下:
![](https://i-blog.csdnimg.cn/blog_migrate/2c52524a14f7a60e79774b6fac2fe280.png)
输出如下:
![](https://i-blog.csdnimg.cn/blog_migrate/60f51bb389429f22c7892cc0e574299b.png)
四、JUnit测试套件
运用场景:开发中,测试类会越来越多,如果要一个个执行测试类会很麻烦,因此可以用测试套件批量执行测试类。
操作步骤:
-
创建三个测试类Test1,Test2,Test3
![](https://i-blog.csdnimg.cn/blog_migrate/455875a852d89c2041d2466e469456d2.png)
//测试类1
public class Test1 {
@Test
public void test() {
System.out.println("测试一");
}
}
//测试类2
public class Test2 {
@Test
public void test() {
System.out.println("测试二");
}
}
//测试类3
public class Test3 {
@Test
public void test() {
System.out.println("测试三");
}
}
-
创建俩个测试套件:TsetAll1,TestAll2(测试套件应当为空,里面没有任何代码块)
-
测试套件添加注解@RunWith(Suite.class)和@SuiteClasses({Test1.class,Test2.class})
//套件1
@RunWith(Suite.class)
@SuiteClasses({Test1.class,Test2.class})
public class TestAll1 {
//@SuiteClasses注解中的Test1,Test2为需要测试的测试类,数量不止可以设置成2个,设置成三个或更多也行。
}
//套件二,测试套件之间是可以嵌套的,比如该套件,嵌套了套件1
@RunWith(Suite.class)
@SuiteClasses({TestAll1.class,Test2.class})
public class TestAll2 {
}
套件一输出结果:
![](https://i-blog.csdnimg.cn/blog_migrate/f2550f229740d16a543dd763e848ce74.png)
套件二输出结果:
![](https://i-blog.csdnimg.cn/blog_migrate/b75d89ef40d827403f6ebc27e317a90e.png)
五、JUnit测试优先级顺序
JUnit是通过@FixMethodOrder注解(annotation)来控制测试方法的执行顺序的。@FixMethodOrder注解的参数是org.junit.runners.MethodSorters对象,在枚举类org.junit.runners.MethodSorters中定义了如下三种顺序类型:
MethodSorters.JVM:按照JVM得到的方法顺序,也就是代码中定义的方法顺序)
MethodSorters.DEFAULT(默认的顺序):以确定但不可预期的顺序执行
MethodSorters.NAME_ASCENDING:按方法名字母顺序执行
六、JUnit内置Rule
-
TemporaryFolder Rule
使用 TemporaryFolderRule 能够创建临时文件和临时文件夹,在方法运行完成后会自动删除掉临时文件跟文件夹(但不校验删除是否成功)。
public class TemporaryFolderRuleTest {
@Rule
public TemporaryFolder tmpFolder = new TemporaryFolder();
@Test
public void test() throws IOException {
//创建一个名称为test.txt的文件
File file = tmpFolder.newFile("test.txt");
System.out.println(file.getName());
}
@Test
public void test1() throws IOException {
//创建一个多级目录a/b的文件夹
File file = tmpFolder.newFolder("a","b");
System.out.println(file.getPath());
}
@Test
public void test2() throws IOException {
//创建一个随机名称的文件
File file = tmpFolder.newFile();
System.out.println(file.getName());
}
@Test
public void test3() throws IOException {
//创建一个随机名称的文件夹
File file = tmpFolder.newFolder();
System.out.println(file.getPath());
}
}
但从 junit 4.13 开始,TemporaryFolder支持配置校验是否删除成功,删除失败则抛出AssertionError异常。且实例化的方式也有区别。
public class TemporaryFolderRuleTest {
//
@Rule
public TemporaryFolder tmpFolder = TemporaryFolder.builder().assureDeletion().build();
@Test
public void test() throws IOException {
//创建一个名称为test.txt的文件
File file = tmpFolder.newFile("test.txt");
System.out.println(file.getName());
}
}
-
ExpectedException Rule
ExpectedException 可以用来校验代码即将发生的异常:
public class ExpectedExceptionRuleTest {
@Rule
public ExpectedException thrown =ExpectedException.none();
@Test
public void test() {
//预期的异常
thrown.expect(RuntimeException.class);
//异常原因
thrown.expectCause(isA(IllegalAccessException.class));
//异常的消息
thrown.expectMessage("This is illegal");
//抛出指定异常
throw new RuntimeException("This is illegal", new IllegalAccessException());
}
}
-
Verifier Rule
Verifier 是一个抽象类,当我们需要在测试用例中验证一些额外的行为的时候,可以使用这个类并重写该类的 verify 方法。
public class VerifierRuleTest {
private List messageLog = new ArrayList<>();
@Rule
public TestName name = new TestName();
//在每个测试用例执行完的时候额外验证一下messageLog 是否为空
@Rule
public Verifier vf = new Verifier() {
//该方法在测试方法执行完后执行,用于额外验证。
@Override
protected void verify() throws Throwable {
System.out.println("vf");
assertFalse("msg Log is not Empty!", messageLog.isEmpty());
}
//该方法为自定义Rule,在方法前后都可以执行,可用于初始化和关闭资源,且重写该方法后,verify方法将不会执行。
@Override
public Statement apply(Statement base, Description description) {
// TODO Auto-generated method stub
return new Statement() {
@Override
public void evaluate() throws Throwable {
System.out.println("测试开始" + name.getMethodName());
//执行测试方法
base.evaluate();
System.out.println("测试完成" + name.getMethodName());
}
};
}
};
@Test
public void test() {
System.out.println("测试1");
messageLog.add("132");
}
@Test
public void test1() {
System.out.println("测试2");
}
}
-
ExternalResourceRule
当做集成测试的时候,有可能需要在执行前准备一些数据(可以是一个文件/数据库连接),并在执行完将准备的数据进行删除。这时候就可以用 ExternalResource Rule 实现。
public class ExternalResourceRuleTest {
@Rule
public ExternalResource re = new ExternalResource() {
@Override
protected void before() {
System.out.println("数据库连接");
}
@Override
protected void after() {
System.out.println("关闭数据库连接");
}
};
@BeforeClass
public static void pulic() {
System.out.println("1");
}
@Test
public void test() {
System.out.println("执行测试");
}
}
-
TestName Rule
该Rule可用于获取当前测试方法的方法名
public class VerifierRuleTest {
//实例化TestName对象
@Rule
public TestName name = new TestName();
@Test
public void test() {
//调用getMethodName()方法获取当前测试方法的名称。
System.out.println("测试:" + name.getMethodName());
}
}
-
自定义 Junit Rule
除了使用 junit 提供的默认 Rule 外,还可以自定义我们自己的 Rule, 自定义 Rule 需要继承 TestRule 接口,并实现其 apply 方法。
public class MyRuleTest {
//2.实例化MyRule类
@Rule
public MyRule myRule = new MyRule();
//3.执行(run)测试方法。
@Test
public void test() {
System.out.println("测试一");
}
//1.自定义Rule类,实现TestRule接口,重写apply方法。
class MyRule implements TestRule{
//
@Override
public Statement apply(Statement arg0, Description arg1) {
return new Statement() {
@Override
public void evaluate() throws Throwable {
//getClassName()方法用于获取当前类名
System.out.println("执行测试方法前" + arg1.getClassName());
//执行测试方法。
arg0.evaluate();
//getMethodName()方法用于获取当前测试方法名称。
System.out.println("执行测试方法后" + arg1.getMethodName());
}
};
}
}
}
-
Rule链
当有多个 Rule 的时候,可以通过 RuleChain 来控制多个 Rule 的执行顺序
public class RuleChainsTest {
@Rule
public RuleChain ruleChain = RuleChain.outerRule(new SimpleMsgLogger("First Rule"))
.around(new SimpleMsgLogger("Second Rule"))
.around(new SimpleMsgLogger("Third Rule"));
@Test
public void test() {
System.out.println("run case");
}
static class SimpleMsgLogger implements TestRule {
private String log;
public SimpleMsgLogger(String log) {
this.log = log;
}
@Override
public Statement apply(Statement base, Description description) {
return new Statement() {
@Override
public void evaluate() throws Throwable {
System.out.println("Starting:" + log);
base.evaluate();
System.out.println("Finishing:" + log);
}
};
}
}
}
七、测试private方法
public class PrivateMethondTest {
//实例化被测试类。
Demo1 d = new Demo1();
@Test
public void test() throws Exception {
//测试没有参数的out()方法
Method method = d.getClass().getDeclaredMethod("out", null);
//要访问私有方法必须将accessible设置为true,否则抛java.lang.IllegalAccessException
method.setAccessible(true);
//调用私有方法。
Object rs = method.invoke(d, null);
System.out.println(rs);
assertNotNull(rs);
}
@Test
public void test1() throws Exception {
//测试有参数的out()方法
Method method = d.getClass().getDeclaredMethod("out", String.class);
//要访问私有方法必须将accessible设置为true,否则抛java.lang.IllegalAccessException
method.setAccessible(true);
//调用私有方法。
Object rs = method.invoke(d, "123");
System.out.println(rs);
}
@Test
public void test2() throws Exception {
//测试有参数的out()方法
Method method = d.getClass().getDeclaredMethod("out", int.class);
//要访问私有方法必须将accessible设置为true,否则抛java.lang.IllegalAccessException
method.setAccessible(true);
//调用私有方法。
Object rs = method.invoke(d, 123);
System.out.println(rs);
}
}