您的位置:首页 > 移动开发 > Objective-C

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
[...]
}

          你已经完全可以在外围控制你的记录和配置行为了!这样你的代码就更加的灵活了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: