PowerMocker,Mockito和Junit 备忘
1. JUnit 是基础,进行单元测试.
参考:http://www.ibm.com/developerworks/cn/java/j-lo-junit4/
1.1 JUnit的常用Annoation:
1. @Test: 测试方法,可以有两个参数(expected=XXException.class,timeout=xxx)
expected 表示期待一个异常,如果实际抛出异常就是这个期待的异常则表示通过测试,
timeout设置一个超时时间,如果测试超过这个时间,则表示测试不通过
2. @Ignore: 忽略测试方法
3. @Before: 每一个测试方法之前运行
4. @After: 每一个测试方法之后运行
5. @BeforeClass: 所有测试开始之前运行,该方法必须是 Public 和 Static 的.
6. @AfterClass: 所有测试结束之后运行,并且该方法必须是 Public 和 Static 的
1.2参数化测试。
你可能遇到过这样的函数,它的参数有许多特殊值,或者说他的参数分为很多个区域。
比如,一个对考试分数进行评价的函数,返回值分别为"优秀,良好,一般,及格,不及格",
因此你在编写测试的时候,至少要写 5 个测试,把这 5 中情况都包含了,这确实是一件很麻烦的事情。
我们还使用我们先前的例子,测试一下"计算一个数的平方"这个函数,暂且分三类:正数, 0,负数。
测试代码如下:
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import static org.junit.Assert. * ;
public class AdvancedTest
{
private static Calculator calculator = new Calculator();
@Before
public void clearCalculator()
{
calculator.clear();
}
@Test
public void square1()
{
calculator.square( 2 );
assertEquals( 4, calculator.getResult());
}
@Test
public void square2()
{
calculator.square( 0 );
assertEquals( 0, calculator.getResult());
}
@Test
public void square3()
{
calculator.square( - 3 );
assertEquals( 9, calculator.getResult());
}
}
为了简化类似的测试, JUnit4 提出了"参数化测试"的概念,只写一个测试函数,
把这若干种情况作为参数传递进去,一次性的完成测试。代码如下:
import static org.junit.Assert.assertEquals;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
import java.util.Arrays;
import java.util.Collection;
@RunWith(Parameterized.class )
public class SquareTest
{
private static Calculator calculator = new Calculator();
private int param;
private int result;
@Parameters
public static Collection data()
{
return Arrays.asList( new Object[][] {{ 2,4 },{ 0,0},{-3,9 },});
}
// 构造函数,对变量进行初始化
public SquareTest( int param, int result)
{
this .param = param;
this .result = result;
}
@Test
public void square()
{
calculator.square(param);
assertEquals(result, calculator.getResult());
}
}
下面我们对上述代码进行分析。首先,你要为这种测试专门生成一个新的类,而不能与其他测试共用同一个类,
此例中我们定义了一个SquareTest类。然后,你要为这个类指定一个Runner,而不能使用默认的Runner了,
因为特殊的功能要用特殊的Runner嘛。
@RunWith(Parameterized.class)这条语句就是为这个类指定了一个ParameterizedRunner。
第二步,定义一个待测试的类,并且定义两个变量,一个用于存放参数,
一个用于存放期待的结果。接下来,定义测试数据的集合,也就是上述的data()方法,
该方法可以任意命名,但是必须使用@Parameters标注进行修饰。
这个方法的框架就不予解释了,大家只需要注意其中的数据,是一个二维数组,数据两两一组,
每组中的这两个数据,一个是参数,一个是你预期的结果。
比如我们的第一组{2, 4},2就是参数,4就是预期的结果。
这两个数据的顺序无所谓,谁前谁后都可以。
之后是构造函数,其功能就是对先前定义的两个参数进行初始化。
在这里你可要注意一下参数的顺序了,要和上面的数据集合的顺序保持一致。
如果前面的顺序是{参数,期待的结果},那么你构造函数的顺序
也要是"构造函数(参数, 期待的结果)",反之亦然。
最后就是写一个简单的测试例了,和前面介绍过的写法完全一样,在此就不多说。
1.3 打包测试。
通过前面的介绍我们可以感觉到,在一个项目中,只写一个测试类是不可能的,我们会写出很多很多个测试类。
可是这些测试类必须一个一个的执行,也是比较麻烦的事情。
鉴于此, JUnit 为我们提供了打包测试的功能,将所有需要运行的测试类集中起来,
一次性的运行完毕,大大的方便了我们的测试工作。具体代码如下:
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
@RunWith(Suite.class )
@Suite.SuiteClasses( {CalculatorTest. class,SquareTest. class } )
public class AllCalculatorTests
{
}
大家可以看到,这个功能也需要使用一个特殊的 Runner,因此我们需要向 @RunWith 标注传递一个参数 Suite.class 。
同时,我们还需要另外一个标注 @Suite.SuiteClasses,来表明这个类是一个打包测试类。
我们把需要打包的类作为参数传递给该标注就可以了。
有了这两个标注之后,就已经完整的表达了所有的含义,因此下面的类已经无关紧要,
随便起一个类名,内容全部为空既可。
1.4 JUnit中的Assert方法
junit中的assert方法全部放在Assert类中,总结一下junit类中assert方法的分类。
(1) assertTrue/False([String message,]boolean condition);
判断一个条件是true还是false。感觉这个最好用了,不用记下来那么多的方法名。
(2) fail([String message,]);
失败,可以有消息,也可以没有消息。
(3) assertEquals([String message,]Object expected,Object actual);
判断是否相等,可以指定输出错误信息。
第一个参数是期望值,第二个参数是实际的值。
这个方法对各个变量有多种实现。在JDK1.5中基本一样。
但是需要主意的是float和double最后面多一个delta的值,可能是误差范围,不确定这个 单词什么意思,汗一个。
(4) assertNotNull/Null([String message,]Object obj);
判读一个对象是否非空(非空)。
(5) assertSame/NotSame([String message,]Object expected,Object actual);
判断两个对象是否指向同一个对象。看内存地址。
(6) failNotSame/failNotEquals(String message, Object expected, Object actual)
当不指向同一个内存地址或者不相等的时候,输出错误信息。
注意信息是必须的,而且这个输出是格式化过的。
2. Mockito
参考:http://rritw.com/a/bianchengyuyan/C__/20120919/226505.html
Mockito 是基于JUnit的,用于单元测试的一个模拟(mock)框架.所谓模拟(mock)是指在单元测试中,
假如我们要测试的类A中需要依赖B类的一个实例,而B类的这个实例在单元测试代码中
不容易获取到.例如,需要测试的类是专门用来测试发送邮件的,假如
就叫MailSender吧,这个类中需要依赖一个User类的实例的email address,通常这个User实例只有在用户
登录系统时才能获取到,而要测试的这个MailSender时(只是单元测试而已),
为了获取到User实例,而在单元测试代码中进行一系列登录授权神马的操作显然太繁琐了,于是mock就派上用场了.
可以使用 User user = mock(User.class); 这样就获得了一个模拟的User实例了.
获取到模拟的User实例还只是开始,因为发邮件时,
需要调用User.getMailAddress()方法获取用户的email,
假如调用了刚刚生成的模拟的User实例的getMailAddress()方法会返回什么呢?
这是mockito框架又发威了,因为它可以模拟方法调用的返回值,也就是说可以设置方法的预期返回值:
使用代码:
when(user.getMailAddress()).thenReturn( "[email protected]" );
使用when(...).thenReturn(...) 格式表示,假如后续代码中有调用
user.getMailAddress()则返回"[email protected]",真是太和谐了.
(注意: 创建mock对象不能对final,Anonymous ,primitive类进行mock)
另外,可对方法设定返回异常
mockito详细文档:
http://docs.mockito.googlecode.com/hg/latest/org/mockito/Mockito.html
3. PowerMocker
PowerMock 也是一个单元测试模拟框架,它是在其它单元测试模拟框架的基础上做出的扩展。
通过提供定制的类加载器以及一些字节码篡改技巧的应用,PowerMock 现了对静态方法、
构造方法、私有方法以及 Final 方法的模拟支持,对静态初始化过程的移除等强大的功能。
因为 PowerMock 在扩展功能时完全采用和被扩展的框架相同的 API, 熟悉 PowerMock 所
支持的模拟框架的开发者会发现 PowerMock 非常容易上手。PowerMock 的目的就是在当前
已经被大家所熟悉的接口上通过添加极少的方法和注释来实现额外的功能,
目前,PowerMock 仅支持 EasyMock 和 Mockito。
参考:http://www.ibm.com/developerworks/cn/java/j-lo-powermock/