junit--用mock object进行隔离测试(上)

原创 2005年02月28日 21:18:00

最近抽空翻译了一下manning出版的junit in action,译的比候捷还糟,大家不要bt.
以下是第7章的内容
第一节   mock object 的介绍:
      隔离测试有很多好处,比如测试那些还没有写出来的代码(只要他有个接口)。另外,隔离测试有利于工作团队对代码的一部分进行测试而不用等到所有的部分都开发完毕。
     但是,可能最大的 好处就是能够写出相关的测试来测试单个方法,而避免其他被调用对象产生副作用.
      MockObject很好的解决了隔离测试问题。Mocks替换了那些对象(你的方法需要调用的),因此产生了一个隔离层 ,从这个角度来看,他和stubs很相似。但是,这是他们唯一的相似点。因为mocks没有实现任何的逻辑(logic):他们只是空壳---提供途径让测试 控制 伪造类的所有商业方法的表现。

     下面是mock object 的定义:
       mock object是一个被用来代替在你程序中被调用的对象的对象。你的代码可以调用mockobject的对象,他产生的结果和你的真实环境中是一样的。
第二节  一个简单的例子:
AccountService为商业逻辑。
AccountManager相当于facade,提供对数据库的存取。
Account的功能相当于vo。
    在没有mocks的情况下,测试AccountService---transfer这个行为将要建立一个数据库,预置一些测试数据,而且还需要部署你的代码到应用服务器(container)等等。尽管这些过程需要在你的应用程序中都要被一一用到,但是对于测试代码逻辑来说他做了太多不必要的工作。
     这个例子的结构示意图如下:

Account.java

package junitbook.fine.tasting;<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

public class Account

{

private String accountId;

private long balance;

public Account(String accountId, long initialBalance)

{

this.accountId = accountId;

this.balance = initialBalance;

}

public void debit(long amount)

{

this.balance -= amount;

}

public void credit(long amount)

{

this.balance += amount;

}

public long getBalance()

{

return this.balance;

}

}
产生简单的account对象,他有两个属性:ID,balance.
AccountManager.java
package junitbook.fine.tasting;

public interface AccountManager

{

Account findAccountForUser(String userId);

void updateAccount(Account account);

}
一个接口。用来控制account对象。有两个方法。
AccountService.java

package junitbook.fine.tasting;

public class AccountService

{

private AccountManager accountManager;

public void setAccountManager(AccountManager manager)

{

this.accountManager = manager;

}

public void transfer(String senderId, String beneficiaryId,

long amount)

{

Account sender =

this.accountManager.findAccountForUser(senderId);

Account beneficiary =

this.accountManager.findAccountForUser(beneficiaryId);

sender.debit(amount);

beneficiary.credit(amount);

this.accountManager.updateAccount(sender);

this.accountManager.updateAccount(beneficiary);

}

}
提供了在账户之间转换金钱的方法。他使用了你先前定义的AccountManager接口来获得account对象并对他进行操作。
        想要测试AccountService.transfer方法。你需要一个mock对象实现AccountManager接口。这样做的原因是因为你的transfer方法使用了这个接口,但是你需要隔离测试。
 MockAccountManager.java
package junitbook.fine.tasting;
import java.util.Hashtable;
public class MockAccountManager implements AccountManager
{
private Hashtable accounts = new Hashtable();
public void addAccount(String userId, Account account)
{
this.accounts.put(userId, account);
//见注释1
}
public Account findAccountForUser(String userId)
{
return (Account) this.accounts.get(userId);
//见注释2
}
public void updateAccount(Account account)
{
// do nothing
//见注释3
}
注释1:addAccount方法用了一个实例变量来作返回值。因为你有许多account对象需要返回,我们用一个hashtable来装载他们。这样可以使mock具有一般性而且支持不同的测试案例:某些测试只建立一个account对象,某些测试可能建立多个account对象。
注释2:addAccount告诉findAccountForUser方法返回什么参数。
注释3:updateAccount更新了一个account但是没有任何的返回值。因此你什么都可以不做。但他被transfer调用的时候,只要被正确更新,他将什么都不用作。

JUnit best practices:不要再mockobject中写入商业逻辑(don’t write business logic in mock objects)
     在写一个mockobject的时候最需要考虑的一点就是不要再其中加入任何的商业逻辑。他必须是一个哑对象(dumb object)只作测试代码让他做的事。环一句话说。他完全靠测试来驱动。这个性质和stubs--包含所有的逻辑--完全相反。
      由两个重要的推论:1,MO很容易产生。2,因为MO只是一个空壳,所以他很难破坏而且不用对他们进行测试。

     现在我们可以对AccountService.transfer进行测试了。
    下面是一个典型的应用mock的测试案例。
      JUnit best practices:只测试那些可能崩溃的部分(only test what can possibly break)
  你可能注意到你并没有模拟account类。原因是因为数据访问对象是不需要被模拟的。他们与环境无关而且十分简单。其他的测试用到了account对象,因此间接的对他进行了测试。如果在这上面操作出现错误,以来他的测试就会报错。在本小节,你已经有了对MO的明确的了解。在下一部分里面,我们将告诉你用mock来写单元测试来重构你的代码

使用Mock Object进行测试

使用Mock Object进行测试作者:kongxxMockObject概述使用Mock Object进行测试,主要是用来模拟那些在应用中不容易构造(如HttpServletRequest必须在Ser...
  • kongxx
  • kongxx
  • 2004年08月23日 10:39
  • 3164

比较完整的junit单元测试之-----mock模拟测试

介绍   本文将介绍模拟测试框架Mockito的一些基础概念, 介绍该框架的优点,讲解应用Mockito的Java示例。 模拟(Mock)的概念    在软件开发的世界之外, "...

JUnit + Mockito 单元测试(一)

未接触 JUnit 之前,曾经对茫茫的代码不知所措……哪怕是自己写的……多写注释?重构代码?甚至为一个方法去写一篇技术文章来解释?——这些都是试过,感觉不是“控制代码”的可行之道,甚至说”徒劳“的。关...

使用junit+mockito进行mock测试实例

刚开始做网站的时候,测试都是这样的(比如测试修改用户信息的表单逻辑):设置断点,启动运行程序,登陆,点击点击点击然后进入到测试的页面,输入测试数据,进入断点…….。一个大的程序启动又慢,还要登陆,还要...

JUnit + Mockito 单元测试(二)

JUnit 是单元测试框架。Mockito 与 JUnit 不同,并不是单元测试框架(这方面 JUnit 已经足够好了),它是用于生成模拟对象或者直接点说,就是”假对象“的工具。两者定位不同,所以一般...

初识stub和mock--junit的两种测试策略

JUnit相信大家都在用,对于如何使用Junit这里不在赘述。Stub和Mock就是两种协助Junit测试的思想或者策略,它们并不是真实存在的对象,却可以模拟真实对象的状态和交互。...

Java单元测试(Junit+Mock+代码覆盖率)

原文见此处单元测试是编写测试代码,用来检测特定的、明确的、细颗粒的功能。单元测试并不一定保证程序功能是正确的,更不保证整体业务是准备的。单元测试不仅仅用来保证当前代码的正确性,更重要的是用来保证代码修...

JUnit + Mockito 单元测试(三)

这里假设我们没有 Tomcat(虽然不太可能,假设吧!),那就使用 Mockito 模拟一个看看怎么样。...

有效使用Mock编写java单元测试

Java单元测试对于开发人员质量保证至关重要,尤其当面对一团乱码的遗留代码时,没有高覆盖率的单元测试做保障,没人敢轻易对代码进行重构。然而单元测试的编写也不是一件容易的事情,除非使用TDD方式,否则编...
  • chjttony
  • chjttony
  • 2013年11月08日 16:04
  • 68813

Mockito实例-Junit & Mockito

前言     前几篇对Mockito的概念及其方法进行了介绍,本篇则提供了一个实例供大家练习,在我们工作中一般都是讲Junit与Mockito相结合一起使用,非常简便。 正题 准...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:junit--用mock object进行隔离测试(上)
举报原因:
原因补充:

(最多只允许输入30个字)