利用IoC模式使类更易于测试

利用IoC模式使类更易于测试


文/陈刚 from http://blog.chengang.com.cn 

有一个需要被测试的类如下:

public   class  ViewManager {
    
private   static  XmlBeanFactory factory  =  Context.getInstance().getXmlBeanFactory();

    
public  View getView(String viewId) {
        List
< ViewBean >  list  =  factory.getViews();
        
for  (ViewBean bean : list) {
            
if  (bean.getId().equals(viewId))
                
return  bean.getView();
        }
        
return   new  NullComposite();
    }


问题:如果要测试getView方法该怎么办呢?

显然由于此方法依赖于factory(XmlBeanFactory ),XmlBeanFactory 内含有比较复杂的逻辑,而且还要读取XML文件,这导致getView不可能被单独测试(一个单元测试的要点:简单独立,一次只测试一个类)。为了让ViewManager能剔除掉XmlBeanFactory,而被单独测试,我们需要做一些改变--让XmlBeanFactory由外界注入,这样就可以写一个逻辑简单的Mock类来替代XmlBeanFactory,实现ViewManager的单独测试。具体实现的方法是加一个构造函数,让XmlBeanFactory可以通过构造函数注入,当然为了保持原有代码的兼容性,默认的factory也不可少。代码如下:

public   class  ViewManager {
    
private   static  XmlBeanFactory factory;

    
public  ViewManager() {
        factory 
=  Context.getInstance().getXmlBeanFactory(); // 默认的factory
    }

    
public  ViewManager(XmlBeanFactory factory) { // 注入的factory
         this .factory  =  factory;
    }

    
public  View getView(String viewId) {
        List
< ViewBean >  list  =  factory.getViews();
        
for  (ViewBean bean : list) {
            
if  (bean.getId().equals(viewId))
                
return  bean.getView();
        }
        
return   new  NullComposite();
    }

测试的代码如下:

public   class  TestViewManager  extends  TestCase {
    
private  ViewManager viewManager;

    @Override
    
protected   void  setUp()  throws  Exception {
        
super .setUp();
        viewManager 
=   new  ViewManager( new  MockXmlBeanFactory());
    }

    
public   void  testGetView() {
        View v 
=  viewManager.getView( " viewId002 " );
        assertEquals(
" viewId002 " , v.getViewId());
        assertEquals(CustomView.
class , v.getClass());
    }

    
public   void  testGetViewByNoneId() {
        View v 
=  viewManager.getView( " abc " );
        assertEquals(
" abc " , v.getViewId());
        assertEquals(NullComposite.
class , v.getClass());
    }

    
private   static   class  MockXmlBeanFactory  extends  XmlBeanFactory { //XmlBeanFactory 的Mock类

        
public  List < ViewBean >  getViews() {
            List
< ViewBean >  views  =   new  ArrayList < ViewBean > ();
            views.add(
new  CustomViewBean( " viewId001 " , NullComposite. class .getName()));
            views.add(
new  CustomViewBean( " viewId002 " , CustomView. class .getName()));
             return  views;
        }

    }
}

在测试的时候报错了,错在assertEquals( " abc " , v.getViewId());。一查是没有把viewId赋给NullComposite对象。纠正错误的办法是:把ViewManager 的getView的方法最后一句改为return new NullComposite(viewId);。这是一个很隐蔽的BUG,以后在这里出问题可真够你花时间找的,现在一下子就测试出来了,这就是测试的好处吧。

你可能感兴趣的:(利用IoC模式使类更易于测试)