单元测试技术JMOCK引用
来源:互联网 发布:图纸软件哪个好 编辑:程序博客网 时间:2024/05/16 12:20
1:MAVEN配置
<dependency>
<groupId>org.jmock</groupId>
<artifactId>jmock-junit4</artifactId>
<version>2.5.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jmock</groupId>
<artifactId>jmock</artifactId>
<version>2.5.1</version>
<scope>test</scope>
</dependency>
2:步骤:
// 1:创建一个Mockery对象
Mockery context = new Mockery();
// 2:创建Mock对象,非常简单
final Session t = context.mock(Session.class);
// 3. 对Mock对象添加预定的期望
context.checking(new Expectations(){
{
//Expectations的语法,需要放在一对大括号之内
//oneOf(t).receive(message);
//will(returnValue(message);
//inSequence(seq);
//其中期望类Expectations将在3.2节详细介绍
}
});
//4. 被测试对象的业务逻辑调用
//5. 查看Mock是否满足被测结果,代码如下:
context.assertIsSatisfied();
3:详细如下:
Expectations的语法如下表所示:
invocation-count (mock-object).method(argument-constraints); [必需]
inSequence(sequence-name);
when(state-machine.is(state-name));
will(action);
then(state-machine.is(new-state-name));
针对Mock对象模拟调用的每一个方法,都应该必须有一个应该必须有一个invocation-count子句,其余子句为可选。
下面对这几个表达式分别作简要的介绍:
invocation-count
invocation-count表示期望的方法的调用次数。其可选的表达形式如下表所示:
oneof / one 期望调用执行一次且仅一次
exactly(n).of 期望调用执行n次
atLeast(n).of 期望调用执行至少n次
atMost(n).of 期望调用执行至多n次
between(min, max).of 期望调用执行至少min次,至多max次
allowing / ignoring 期望调用执行任意多次,包括0次
never 不期望调用执行
具体使用如下所示:
exactly(4).of(subscriber).receive(message);
atMost(2).of(subscriber).receive(message);
atLeast(4).of(subscriber).receive(message);
atLeast(2).of(subscriber).receive(message);
二:模拟泛型接口
模拟泛型
public interface Juicer<T extends Fruit> { Liquid juice(T fruit);}
那些行,虽然在语句结构和语义上都是正确的,但是产生了安全警告.为了避免这些警告,你必须使用@SuppressWarnings注释变量声明:
@SuppressWarnings("unchecked")
Juicer<Orange> orangeJuicer =(Juicer<Orange>) context.mock(Juicer.class, "orangeJuicer");
@SuppressWarnings("unchecked")
Juicer<Coconut> coconutJuicer =(Juicer<Coconut>) context.mock(Juicer.class, "coconutJuicer");
三:使用jMock和ClassImposteriser模拟类
ClassImposteriser创建模拟实例不需要调用模拟类的构造函数.所以带有有参数或调用可覆盖的对象方法的构造函数的类可以被安全的模拟.然而ClassImposteriser不能创建最终类或最终方法的模拟.
private Mockery context = new Mockery() {{
setImposteriser(ClassImposteriser.INSTANCE);
}};
四:user、UserService、UserDao
对UserDao进行mock模拟,表达式如下:
userDAO = new Mock(UserDAO.class);
userService.setUserDAO((UserDAO)userDAO.proxy());
userDAO.expects(once()).method("getUser").with(eq(1L)).will(returnValue(fakeUser));
1) userDAO.expects(once()):我们期望userDAO的某方法被执行一次,如果此方法未被执行,或者执行了二次以上,测试就不会通过
2) method("getUser"):这个期望被执行一次的方法名为userDAO.getUser()
3) with(eq(1L)):执行getUser()方法时,确认其传入的参数值为“1L”
4) will(returnValue(fakeUser)):上述条件均满足后,返回一个虚假的对象,即我们前面实例化的fakeUser。
对于Mock类有很多API可供使用比如:
isA(Class clz) 表示为某个类
isVoid 将will换成isVoid表示无返回值
异常测试:
allowing(dao).find(id);will(throwException(new FindException()));//也可以throw RuntimeException
可以在mock方法时做一些参数操作:
allowing(srv).findUser(with(lessThan(10)));will(returnValue(user1));
五:表达式如下:
invocation-count mock调用频率。oneOf表示调用一次后这个expections即失效。
mock-object mock对象。即上面Mockery创建的对象。
method 用mock代替实现接口的一个方法。所以mock必须使用接口编程。
argument-constraints mock参数条件。即mock指定方法的参数。
when … will…then … 类似于if .. else… 这样的语句。简单的条件表达式
action mock符合条件后,执行操作。一般是返回结果。或者抛出异常
state-machine 条件表达式。
下面详细讲解下expectations各个部分。
Invocation CountoneOf 只执行一次
exactly(n).of 执行指定n次
atLeast(n).of 至少执行n次
atMost(n).of 最多执行n次
between(min,max).of 可以执行min-max次
allowing 允许执行,不受限制
ignoring 功能同allowing类似。这里主要字面上区分allowing
never 不允许执行
Actionswill(returnValue(v)) 返回一个值。Object类型任意。集合类型不建议这里返回。虽然也可以
will(returnIterator(c)) 返回一个集合类型的值。
will(returnIterator(v1, v2, …, vn)) 返回一个集合类型的值。可以用多个,来分隔。
will(throwException(e)) 抛出一个异常。
will(doAll(a1, a2, …, an)) 嵌套执行多个actoin。不常用。
参数为对象:
allowing(loginCommand).setService(with(same(dataService)));
inSequence(classSequence);
will(returnValue(dataService));
六:mock类中的private
执行private方法,mock类中的私有方法:
//DateUtil.class,要Mock的类
new Expectations(DateUtil.class) {
{
//执行DateUtil的now方法
invoke(DateUtil.class,"now");
//期望方法返回的结果
result = mockDate();
}
};
Assert.assertEquals("2010-07-22 15:52:55", DateUtil.getCurrentDateStr());
mock 某个类的私有属性:
@Test
public void testPrivateFiled() {
final DateUtil dateUtil =new DateUtil();
new Expectations(dateUtil){
{
this.setField(dateUtil, "count", 2);
}
};
Assert.assertEquals(2, dateUtil.getCount());
}
•关键词:Verifications 想验证被Mock的类的某个方法是否被调用
new Verifications() {
{
remote.doSomething(anyInt);
times = 0;//调用次数,0表示上面方法不会被调用
}
};
avatar-gen工具
public class TestLoginCommandExecutor {
private Mockery classContext = null;
private LoginCommandExecutor loginCommand = null;
private Mockery interfaceContext = null;
private DataService dataService = null;
private Session session = null;
private ResponseGenerator responseGenerator = null;
@Before
public void setUp() throws Exception {
classContext = new Mockery() {
{
setImposteriser(ClassImposteriser.INSTANCE);
}
};
loginCommand = classContext.mock(LoginCommandExecutor.class);
interfaceContext = new Mockery();
session = interfaceContext.mock(Session.class);
dataService = interfaceContext.mock(DataService.class);
}
@After
public void tearDown() throws Exception {
loginCommand = null;
classContext = null;
interfaceContext = null;
dataService = null;
session = null;
responseGenerator = null;
}
@Test
public void testSetDataService() {
classContext.checking(new Expectations() {
{
oneOf(loginCommand).setService(with(same(dataService)));
will(returnValue(null));
}
});
loginCommand.setService(dataService);
classContext.assertIsSatisfied();
Assert.assertNotNull("DataService为空!", dataService);
}
@Test
public void testLoginExecutor() throws IOException {
final String commandName = "Login";
final Command command = new Command();
command.addProperty("user", "admin");
command.addProperty("password", "0f52903a303478324f8ffd479d300259");
command.addProperty("version", "5.0");
final ByteBuffer data = ByteBuffer.allocate(10000);
interfaceContext.checking(new Expectations() {
{
oneOf(dataService).authorize("admin",
"0f52903a303478324f8ffd479d300259");
will(returnValue(2));
oneOf(session).putAttribute(
DataServiceServerConstants.USER_INFO, "admin");
oneOf(session).putAttribute(
DataServiceServerConstants.PASSWORD,
"0f52903a303478324f8ffd479d300259");
oneOf(session).changeState(DataServiceState.Idle);
}
});
responseGenerator = new ResponseGenerator();
responseGenerator.setCommandName(commandName);
final LoginCommandExecutor login = new LoginCommandExecutor();
login.setService(dataService);
Assert.assertNotNull("DataService为空!", dataService);
Assert.assertNotNull("Command为空!", command);
login.execute(command, data, session, responseGenerator);
Assert.assertNotNull("Session为空!", session);
interfaceContext.assertIsSatisfied();
}
@Test
public void testGetName() {
final LoginCommandExecutor login = new LoginCommandExecutor();
final String name = login.getName();
Assert.assertEquals("Login", name);
}
二:
UploadServiceImpl uploadServiceImpl = new UploadServiceImpl();
@Test
public void testGetFile() {
final TestSourceFile testSourceFile = new TestSourceFile();
final int groupId = 6;
final String fileName = "test.txt";
interfaceMock.checking(new Expectations() {
{
oneOf(dataServiceDao).getFile(groupId, fileName);
will(returnValue(testSourceFile));
}
});
uploadServiceImpl.setDao(dataServiceDao);
Assert.assertNotNull("DataServiceDao为空!", dataServiceDao);
final TestSourceFile testSource = uploadServiceImpl.getFile(groupId,
fileName);
Assert.assertNotNull("TestSourceFile为空!", testSource);
interfaceMock.assertIsSatisfied();
}
- 单元测试技术JMOCK引用
- 使用jMock辅助单元测试
- 使用jMock辅助单元测试
- 24分钟学会用JMock进行单元测试
- 24分钟学会用JMock进行单元测试
- 24分钟学会用JMock进行单元测试
- 24分钟学会用JMock进行单元测试
- JMock
- Jmock
- JMOCK
- jmock
- 单元测试框架JMock与Mockito的用法比较
- 单元测试技术
- 单元测试时引用文件
- 单元测试及框架简介 --junit、jmock、mockito、powermock的简单使用
- 单元测试及框架简介 --junit、jmock、mockito、powermock的简单使用
- 单元测试及框架简介 --junit、jmock、mockito、powermock的简单使用
- [JMock] JMock快速入门
- 移动应用实用测试指南
- Cache系列Ehcache
- IOS学习笔记(11)TableView中移动cell和section
- MySQL 锁
- php正则匹配图片
- 单元测试技术JMOCK引用
- 寒假集训作业(5)——递归与递推
- tomcat下部署solr 4.0
- JDBC的数据格式
- 杭电ACM 2047 阿牛的EOF牛肉串
- EasyMock应用
- double 转char的一个方法sprintf_s
- 关闭FORM时出现红色进度条
- “如果你倾尽全力,只是为了击败在做同样工作的其他公司,那这样的工作怎么会令人兴奋?这就是许多公司衰落的原因。