JUnit学习笔记8---mock object进行独立测试2
2010-02-03 09:17
501 查看
使用mock objects,重构将变得容易!
有些人说过,单元测试应该对测试中的代码透明:你不应为了简化测试而改变运行时的代码。这是错误的!单元测试是对运行时代码最好的运用。应该同其他运用同等的看待。如果你的代码不能在测试中运用,你应该纠正代码。
例如,你看下面的代码怎样?
[...] import java.util.PropertyResourceBundle; import java.util.ResourceBundle;; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; [...] public class DefaultAccountManager implements AccountManager{ private static final Log LOGGER= LogFactory.getLog(AccountManager.class); public Account findAccountForUser(String userId){ LOGGER.debug("Getting account for user ["+userId+"]"); ResourceBundle bundle= PropertyResourceBundle.getBundle("technical"); String sql=bundle.getString("FIND_ACCOUNT_FOR_USER"); // Some code logic to load a user account using JDBC [...] } }
用LogFactory取得一个Log对象。用PropertyResourceBundle获得了SQL命令。
重构所有的代码以传递领域对象是件费时的事。也许你不准备重构整个程序,而仅仅是为了一个单元测试,幸运的是这里有方便的重构技术,让你的代码保持相同的接口,并传递给它没有创建的域对象。让我们看看重构后的DefaultAccountManager类是什么样的!
[...] import java.util.PropertyResourceBundle; import java.util.ResourceBundle;; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; [...] public class DefaultAccountManager implements AccountManager{ private Log logger; private Configuration configuration; public DefaultAccountManager() { this.LogFactory.getLog(DefaultAccountManager.class), new DefaultConfiguration("technical")); } public DefaultAccountManager(Log logger, Configuration configuration) { this.logger=logger; this.configuration=configuration; } public Account findAccountForUser(String userId){ this.logger.debug("Getting account for user["+userId+"]"); this.configuration.getSQL("FIND_ACCOUNT_FOR_USER"); } }
注意到,它使用了一个全新的Configuration接口,替换了前一个代码上的PropertyResourceBundle类。由于引入了一个接口(这很容易mock),同
时Configuration接口可以实现你想要的任何东西,这就使得代码变得灵活!你可以用Log和Configuration接口实现任何的实现复用DefaultAccountMan
ager类。这个设计变得更加的优秀了。类可以由外围(它的调用者)控制,同时你并没有破坏已有的接口,因为你只是添加了一个新的构造函数,同时还保留
了原有的构造函数,它仍然对logger和configuration进行初始化,赋给成员默认值。
重构提供了在测试中控制领域对象的一个暗门。在保留向后兼容性的同时,也重构了一条通向未来的路!
允许灵活的代码
我们在前面描述了一个设计模式称为控制反转(IOC)的著名模式。主要的想法是从类/方法之外实例化所有的
领域对象,同时传递各种参数。对象实例是传递给类的(通常通过接口),而不是由类来创建对象实例。在上面的例子中,这表现在把Log和Configuration对像传递给DefaultAccountManager类。DefaultAccountManager没有表明传递了哪些实例以及他们是如何构造的。只知道Log和Configuration的接口。
IOC使单元测试变得简单,为了证明这点,让我们看看你可以多么简单的进行findAccountByUser测试!
public void testFindAccountByUser(){
MockLog logger=new MockLog();
MockConfiguration Configuration=new MockConfiguration();
Configuration.setSQL("SELECT*[...]");
DefaultAccountManager am=
new DefaultAccountManager(logger,configuration);
Account account=am.findAccountForUser("1234");
//Perform asserts here
[...]
}
你已经完全可以在外围控制你的记录和配置行为了!这样你的代码就更加的灵活了。
相关文章推荐
- JUnit学习笔记8---mock object进行独立测试2
- JUnit学习笔记9---mock object进行孤立测试3
- JUnit学习笔记10---mock object进行孤立测试4
- JUnit学习笔记10---mock object进行孤立测试4
- JUnit学习笔记7---mock objects进行孤立测试1
- JUnit学习笔记6---用stub进行粗粒度测试
- JUnit学习笔记7---mock objects进行孤立测试1
- Hibernate4与Spring4整合,使用Junit4测试相关学习笔记
- JUnit学习笔记6---用stub进行粗粒度测试
- JUnit学习笔记3——chapter4.探索软件测试
- JUnit学习笔记14---对JSP和taglib进行单元测试1
- JUnit学习笔记15---对JSP和taglib进行单元测试2
- JUnit学习笔记20---对数据库应用程序进行单元测试4
- php学习笔记1——使用phpStudy进行php运行环境搭建与测试。
- junit---用mock object进行隔离测试(下)
- Junit学习笔记之一:junit的安装和测试原则
- 雾山的Robotium学习笔记---使用junitreport导出测试报告
- JUnit测试驱动开发学习笔记1
- TDD学习笔记【三】---是否需针对非public方法进行测试?
- Junit学习笔记之-- 测试套件