(转)用Mock Object进行独立单元测试(Testing in isolation with mock objects)
来源:互联网 发布:淘宝有吕官方旗舰店 编辑:程序博客网 时间:2024/05/04 06:00
用Mock Object进行独立单元测试(Testing in isolation with mock objects) 独立测试就是单独测试一个类或方法里的代码,而不测试里面调用的其他类或方法的代码。即假定调用的其他类或方法都正常执行。 假定我们有对象A,它内部频繁调用了B中的方法。但是除了调用B的部分还存在自己的逻辑代码。这时,我们只想写A的单体测试,而不想测试B(因为B可能还没编写,只写了实现的接口或者B运行太慢了影响我们的测试效率)。这样的话,我们就需要创建B的Mock对象。 换言之,我们现在不关心B,我们假定B的行为都能正常运行。我们的目标是假定B运行正常的情况下,来对A进行单体测试。 Mock对象就是我们先不用关心的对象,但是我们的关注对象对它有调用,所以我们给关注对象准备个假货让它用。 现在我们写好了类AccountService,具体如下 现在我们想测试transfer方法,它内部调用的AccountManager的两个方法。但是对于AccountManager来说,它只是个接口,如下: 所以现在我们必须些个MockAccountManager对象。而且里面的方法体都是非常简单的,就是假定它就返回某某值。 我们这里还有Account类 由于这里的Account类非常的简单,以至于我们在测试AccountService的时候,创不创建Account的Mock对象都一样,那么我们为什么不用真实的对象测试呢。这时我们可以回想一下我们使用Mock对象的那些种场合。 下面是对AccountService的transfer方法的测试 这里我们在假定AccountManager方法都工作正常的情况下,完成了对transfer方法的测试。 EasyMock和jMock都是Open Source,前者在sourceforge,后者在codehaus。对这些OSS的应用可以简化我们对Mock对象的时候,大部分情况下不用手动创建Mock对象。 现在我们还是要测试AccountService的transfer方法,我们写了AccountService2Tests类。 这里我们没有使用MockAccountManager对象,而是用EasyMock创建的动态Mock对象。所以我们就不用手动编写Mock对象了。 下面是用jMock写的测试AccountService的transfer方法的AccountService3Tests单体测试 从上面的测试可以看到,在使用jMock做测试的时候,必须继承的是MockObjectTestCase。因为要使用once,same,returnValue等方法。其他的和EasyMock基本上相似,只是jMock更容易理解一点。 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); } }
public interface AccountManager { Account findAccountForUser(String userId); void updateAccount(Account account); }
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; } public String getAccountId() { return accountId; } }
public class AccountService1Tests extends TestCase { public void testTransfer(){ AccountService as = new AccountService(); MockAccountManager mockAccountManager = new MockAccountManager(); Account accountA = new Account("A",3000); Account accountB = new Account("B",2000); mockAccountManager.addAccount(accountA); mockAccountManager.addAccount(accountB); as.setAccountManager(mockAccountManager); as.transfer("A","B",1005); assertEquals(accountA.getBalance(),1995); assertEquals(accountB.getBalance(),3005); } }
public class AccountService2Tests extends TestCase{ public void testTransfer(){ // setup //创建MockControl对象,关联到AccountManager MockControl control = MockControl.createControl(AccountManager.class); //得到一个运行中的mock对象 AccountManager mockAccountManager =(AccountManager) control.getMock(); AccountService as = new AccountService(); as.setAccountManager(mockAccountManager); //expect /* 设定Mock对象的行为 */ Account accountA = new Account("A",3000); Account accountB = new Account("B",2000); //设定在运行中执行方法findAccountForUser("A"),并且让它返回accountA对象。 mockAccountManager.findAccountForUser("A"); control.setReturnValue(accountA); //设定在运行中执行方法findAccountForUser("B"),并且让它返回accountB对象。 mockAccountManager.findAccountForUser("B"); control.setReturnValue(accountB); //设定在运行中执行方法updateAccount(accountA)。 mockAccountManager.updateAccount(accountA); mockAccountManager.updateAccount(accountB); /* 带Mock对象运行测试 */ control.replay(); as.transfer("A","B",1005); assertEquals(accountA.getBalance() , 1995); assertEquals(accountB.getBalance() , 3005); control.verify(); } }
public class AccountService3Tests extends MockObjectTestCase { public void testTransfer(){ Mock mock = new Mock(AccountManager.class); AccountManager mockAccountManager =(AccountManager)mock.proxy(); AccountService as = new AccountService(); as.setAccountManager(mockAccountManager); Account accountA = new Account("A",3000); Account accountB = new Account("B",2000); // expectations mock.expects(once()).method("findAccountForUser").with(same("A")).will(returnValue(accountA)); mock.expects(once()).method("findAccountForUser").with(same("B")).will(returnValue(accountB)); mock.expects(once()).method("updateAccount").with(same(accountA)).isVoid(); mock.expects(once()).method("updateAccount").with(same(accountB)).isVoid(); //excute as.transfer("A","B",1005); assertEquals(accountA.getBalance() , 1995); assertEquals(accountB.getBalance() , 3005); verify(); } }
- (转)用Mock Object进行独立单元测试(Testing in isolation with mock objects)
- [原创]用Mock Object进行独立单元测试(Testing in isolation with mock objects)
- Mock Objects in Unit Testing
- 使用mock进行单元测试
- Mock Objects in Unit Tests
- JUnit学习笔记8---mock object进行独立测试2
- JUnit学习笔记8---mock object进行独立测试2
- Mock Object: 把单元测试进行到底
- 单元测试的扩展:mock object
- 单元测试的扩展:mock object
- 单元测试的扩展:mock object
- Mock Objects
- Mock Objects
- 使用mock object做单元测试,mock object如何插入?
- 使用MOCK对象进行单元测试
- 使用 MOCK 对象进行单元测试
- 使用MOCK对象进行单元测试
- 使用mock进行java单元测试
- C++指针变量的用途
- alfresco默认的权限许可模型参考
- 嵌入式软件笔试总结
- 互联网公司7种衰亡
- iText在Linux下使用不同中文字体问题的解决方法
- (转)用Mock Object进行独立单元测试(Testing in isolation with mock objects)
- 做人学问(转)
- 项目经理如何让团队发挥最大潜能
- 正则表达式
- 单目运算符++ --
- 云端软件平台与虚拟系统大比拼
- [转]Trie树
- SQL Server 索引结构及其使用(一)
- 输入焦点