欢迎浏览我的博客 获取更多精彩文章
Junit的基本使用
环境安装
基本的Junit环境安装很简单,只需要junit和hamcrest-core两个依赖包即可.在这里为了方便,直接用Maven来配置依赖
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
一个简单的例子
我们先来一个最简单的例子作为示范,这个类只有一个方法,上面加上了@Test注解作为测试方法的声明
import org.junit.Test;
/**
* @author Boyn
* @date 2019/9/6
* @description 开始测试!一个简单的测试类
*/
public class BeginTest {
@Test
public void sayTest() {
System.out.println("Test");
}
}
他的结果如下
Assert方法组
在Junit中,一个非常有用的功能就是Junit中的断言方法组
他通过
import static org.junit.Assert.*;
来进行引入.
Assert方法组的功能十分强大,主要来说,他有以下功能
- 判定数组是否相等 – (assertArrayEquals)
- 判定对象或基本类型等是否相等(类需要实现自己的equals方法) – (assertEquals)
- 判定传入的条件是否为真 – (assertTrue & assertFalse)
- 判定传入的对象是否为空 – (assertNull & assertNotNull)
- 判定传入的两个引用是否指向同一个对象 – (assertSame & assertNotSame)
- 实现更加复杂的匹配条件(与matcher相比较,matcher在下面讲到) – (assertThat)
具体用法可以见这个类
import org.junit.Test;
import static org.junit.Assert.*;
/**
* @author Boyn
* @date 2019/9/6
* @description Assert方法组
*/
public class AssertTest {
public String concat(String s1, String s2) {
return s1 + " " + s2;
}
public boolean returnTrue() {
return true;
}
@Test
public void concatTest() {
assertEquals("hello junit",concat("hello","junit"));
}
@Test
public void isArrayEquals(){
int[] array1 = new int[]{1, 2, 3};
int[] array2 = new int[]{1, 2, 3};
assertArrayEquals(array1,array2);//通过实现equals方法,还可以比较对象数组是否相同
}
@Test
public void isTrue(){
assertTrue(returnTrue());
}
@Test
public void isNull(){
assertNull(null);
}
@Test
public void isSame(){
//由于hello字符串在常量池中,所以s1和s2指向的是同一个对象
String s1 = "hello";
String s2 = "hello";
assertSame(s1,s2);
String s3 = new String("boyn.top");
String s4 = new String("boyn.top");
assertNotSame(s3,s4);
}
}
Matcher方法
matcher是比普通的assert方法组更强大的方法,他会接受一个输入的参数与条件参数(matcher类),返回对条件的相应.junit中(准确来说是Hamcrest)已经定义好了一些直接能用的matchers类.我们可以导入
import static org.hamcrest.CoreMatchers.*;
一个简单的类是 is() 类,对里面的对象与输入的对象调用equals(),返回相同时,返回值为真
import static org.junit.Assert.*;
import static org.hamcrest.CoreMatchers.*;
import org.junit.Test;
/**
* @author Boyn
* @date 2019/9/6
* @description Matcher类
*/
public class MatcherTest {
@Test
public void testWithMatchers(){
assertThat("this string", is("this string"));
assertThat(123, is(123));
}
}
matcher一个好用的功能是可以链式调用,
@Test
public void testWithMatchers() {
assertThat(123, not( is(345) ) );
}
如我们可以将is()嵌套在not()里面,可以构成一个is not的环境条件
我们来看一些matchers的实例
Core
- any() – 对任何对象返回true
- is() – 检查matcher的对象与输入对象是否匹配
- describedAs() – 对Matcher增加描述
Logical
- allOf() – 接受matchers数组,当所有matcher返回true的时候才匹配
- anyOf() – 接受matchers数组,当有一个matcher返回true的时候就匹配
- not() – 对matcher返回的结果取反
Object
-
equalTo() – 与is()相似
-
instanceOf() – 检查输入的对象是否为类X的实例或子类实例
-
notNulValue()/nullValue() – 检查输入对象是否为空
-
sameInstance() – 检查输入对象是否与另一个是同样的对象
这些matcher的方法都是接收不同对象的静态方法,他们会返回一个mathcer对象以支持链式调用
对异常进行测试
有些时候想要测试对特定的方法和输入,是否会返回正确的异常,或者说,是否会在特定的状态下抛出异常.
第一种方法,是我们在@Test注解中说明,如
import org.junit.Test;
/**
* @author Boyn
* @date 2019/9/7
* @description
*/
public class ExceptionTest {
@Test(expected = IllegalArgumentException.class)
public void testForException(){
throw new IllegalArgumentException("Argument invalid");
}
}
这个方法说明我们会对IllegalArgumentException进行检查,如果没有抛出这个异常,则测试失败
第二种方法是我们可以用一个try-catch方法块对想要进行测试的方法进行包裹.
@Test
public void testForException2(){
try {
testForException1();
fail("failed");
} catch (IllegalArgumentException e) {
e.printStackTrace();
}
}
如果没有抛出异常,那么就会继续往下执行到方法fail,它是属于Assert方法组中的,标记测试失败
Stub,Mock和代理测试
Mock测试就是对一个真实对象的替代进行测试,称之为Mock.比如说,我们有一个Calculator的类,然后我们需要去访问数据库中的数据来进行计算,那么数据访问对象,即dao层对象就是我们所说的真实对象.为了去分离测试的环节,我们要mock一个数据访问对象来对Calculator来进行测试
为了实现一个dao,我们可能需要先连接数据库,然后预先插入一些数据.这样很麻烦,所以我们可以做一个假的dao,只用把数据写在对象中,返回我们需要的数据,而不需要连接数据库.这个假的dao就是我们通常所说的mock对象.mock对象不仅可以对上测试Calculator的可用性,也可以对下测试真dao对数据库的连接性.
一般来说,mock对象是泛指以下三种对象,Stubs,Mocks和Proxies,他们都是假对象的一种模式.在单元测试中,他们用来作为单元的协作者.
Stub是实现了某个接口的部件,不过不是返回这个接口部件被调用时返回的值,而是返回适合单元测试的值.使用stub可以测试一个单元是否能够处理不同返回的值.
Mocks与Stub相似,不过Mocks不仅可以测试单元是否可以处理多样的数据,还可以测试单元是否可以正确地调用方法,比如说,是否在适当的时候调用特地的方法.这个特性就是通过代理模式来实现的
Proxies将mock的方法代理起来.
不可否认的是,Mock确实很有用,但是很多时候,是不足够的.