最近抽空翻译了一下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;
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来写单元测试来重构你的代码
来源:http://blog.csdn.net/huabingl/article/details/305778
相关推荐
Mock Object是一种在单元测试中模拟真实对象的行为和交互的技术,它允许测试人员控制对象间的依赖关系,从而在隔离环境中测试单个组件。这样可以避免复杂的真实系统依赖,提高测试的效率和准确性。 首先,Eclipse是...
使用 Mockito 和 JUnit 进行单元测试,是遵循测试驱动开发原则的良好实践。先编写测试,再编写实现,有助于保证代码质量,减少缺陷,同时也有助于设计更好的 API。 10. **持续集成(CI)**: 将这些测试集成到...
Hamcrest是一个匹配器库,与JUnit等测试框架结合使用,提供了一种声明式的方式来编写断言。它的优势在于其表达性强,使得测试代码更加可读。例如,你可以使用`assertThat(result, is(equalTo(expected)))`来验证结果...
阅读指引: 第一部分:Junit精粹 第1章:带着你为一个简单的对象创建测试。在此过程中介绍了单元测试的好处,... 第7章:展示了Mock object方法,这是一种让你可以把代码从周围领域对象隔离出来的测试的方法。 ......
本培训资料将引导你深入理解Maven的项目管理机制,掌握JUnit的测试方法,以及如何使用Mock工具进行单元测试。通过学习这些内容,你将能更高效地进行Java开发,提高代码质量,并为团队合作打下坚实基础。
通过以上内容,你将具备使用JUnit进行单元测试的基础能力,能够编写、运行和调试测试用例,有效保障代码的质量和稳定性。深入实践,结合实际项目,你将更加熟练地运用JUnit解决各种测试挑战,成为单元测试的高手。
5. **验证行为**:最后,使用 `verify()` 方法检查 mock 对象的调用是否符合预期,如:`verify(mockObject).someMethod()`。 ### 相关工具比较 GMock 在 Groovy 中与其他模拟工具如 JUnit、EasyMock 和 JMock 有...
在软件开发过程中,单元测试是确保代码质量的重要环节,而模拟对象(Mock Object)在单元测试中扮演着至关重要的角色。EasyMock是一款广泛使用的Java模拟框架,它允许开发者创建和控制模拟对象,以便在测试中隔离被...
这通常需要使用依赖注入(Dependency Injection)技术,使测试时可以替换掉真实的依赖,用模拟对象(Mock Object)或存根(Stub)来控制它们的行为。 4. 断言:断言是测试用例的核心,它用来检查被测试代码的结果...
通过这样的例子,开发者可以学习如何有效地组织测试代码,如何使用Mockito来模拟复杂的依赖关系,以及如何利用JUnit进行测试驱动开发。理解并熟练掌握JUnit和Mockito,不仅有助于提高代码质量,还能使开发过程更加...
它可以与JUnit或TestNG结合使用,进行功能测试和端到端测试。 8. 持续集成/持续部署(CI/CD):持续集成工具如Jenkins、GitLab CI/CD可以帮助自动化测试流程,每次代码提交后自动触发构建和测试,确保代码质量。 9. ...
综上所述,“单元测试一条龙”文档不仅介绍了面向对象的基本概念,还详细讲解了如何使用JUnit进行单元测试、如何利用Feed4JUnit进行参数化测试、JUnitPerf进行性能测试以及如何使用Selenium进行自动化测试。...
JUnit4提供了`Mockito`库支持,通过`@Mock`和`@InjectMocks`注解,我们可以创建并注入模拟对象,以确保测试只关注被测代码的行为,而不是依赖的外部组件。 总结来说,JUnit4.x以其简洁、易用的特点,成为了Java单元...
在实际项目中,jMock常与其他测试框架如JUnit或TestNG结合使用,形成一套完整的测试解决方案。例如,可以使用jMock定义模拟对象的期望,然后在JUnit的测试方法中执行这些期望并验证结果。 总结来说,jMock 2.6.0-...
7. **Mock对象**:JUnit可以与其他mocking框架如Mockito结合,用于模拟协作对象,隔离被测试代码。 8. **测试监听器**:JUnit允许添加测试监听器,扩展测试过程,如报告生成、性能度量等。 在“jar”标签下,我们...
在传统的单元测试中,我们通常会使用诸如Mockito这样的工具来创建模拟对象,以隔离被测试代码和其依赖。JMock不仅提供了模拟对象的功能,还能记录和验证对象的方法调用,这对于测试驱动开发(TDD)和行为驱动开发...
Java自动化测试是软件开发过程中的一个重要环节,它利用专门的工具和框架,通过编写可执行的代码来替代手动进行重复性的测试任务,提高测试效率,减少人为错误,并且能够更好地集成到持续集成/持续部署(CI/CD)流程...
5. **Mockito框架**:为了隔离测试,可能会使用`Mockito`来模拟依赖服务,比如当认证服务依赖于数据库时,可以通过mock数据库来简化测试。 6. **Hamcrest匹配器**:用于断言预期结果,如`assertThat()`方法配合`...