通过反射准备单元测试数据

      (edit by king)在编写单元测试的时候,一般提倡将测试数据和测试代码分离。这样做的好处在于, 测试数据的管理方便,增加和减少测试数据都会相对方便一点。

通常,我们可以模仿junit提供的参数化这样的方法,将测试数据进行分类,变成多个test case。 其中可能会遇到的最大麻烦就是数据准备的格式,和如何通过数据文件,生成测试需要的数据。

      我尝试使用xml方式来定义数据,xml的最大好处,就是能够通过标签和属性,自定义各种java的数据类型。 包括基本数据类型(如int, double, boolean等),数组类型,java bean等。 这里就介绍下这些数据类型的创建方法。

      java提供了强大的反射机制,能够在运行时根据名称创建需要的对象。这里所有的对象创建都需要用到。 首先,对于基本数据类型,可以发现,通过int.class可以创建int的Class对象,但是却没有办法通过 Class.forName("int")来创建这个Class对象。所以,对于创建这种基本数据类型,我是通过对名称的判断, 创建对应的Class对象的。创建代码如下:

private Class<?> getClassName(String valueType) throws ClassNotFoundException {
    if ("boolean".equals(valueType)) {
        return boolean.class;
    } else if ("char".equals(valueType)) {
        return char.class;
    } else if ("int".equals(valueType)) {
        return int.class;
    } else if ("long".equals(valueType)) {
        return long.class;
    } else if ("short".equals(valueType)) {
        return short.class;
    } else if ("byte".equals(valueType)) {
        return byte.class;
    } else if ("float".equals(valueType)) {
        return float.class;
    } else if ("double".equals(valueType)) {
        return double.class;
    } else {
        return Class.forName(valueType);
    }
}

       用前面的代码,能够根据名字创建出对象的Class对象,再通过apache的ConvertUtils, 将Class对象和通过数据文件获取的对象值(String类型),这样就能够创建基本数据类型、数组 和java对象的创建。

 

      ConvertUtils帮我们实现了基本数据类型和它们数组,BeanUtils帮我们创建了需要的java bean。 但是,我们在测试异常数据的时候,往往还需要准备一类特殊的对象——异常。

为了能够不增加标签,我们仍然采用了原来的创建数据的value标签。这样,就需要在原来创建普通对象 的时候,对异常类型进行判断。根据原来的源码,是通过ConvertUtils.convert这个静态方法, 将文本内容和Class对象转换为制定对象的实例。通过对ConvertUtils代码的查看,它内部仅仅对 部分类型,有现成的实现,对于没有注册的类型,只会返回一个String对象。

      因此,最方便的扩展方法,就是当Class对象是Exception的扩展类时,向ConvertUtils里面注册一个 转换对象。部分代码如下:

if(Exception.class.isAssignableFrom(valueTypeClass)) {
	ConvertUtils.register(new ExceptionConverter(), valueTypeClass);
}

 ExceptionConverter的实现非常简单,如果有内容,则作为异常对象的消息,在构造时传入 (这个应该用处不大,测试的时候,一般只会判断是否有期望的异常抛出)。具体的实现:

public class ExceptionConverter extends AbstractConverter { 

    @SuppressWarnings("unchecked")
    @Override
    protected Object convertToType(Class type, Object value) throws Throwable {
        if (value instanceof String) {
            try {
                Constructor c = type.getConstructor(String.class);
                return c.newInstance(value);	
            } catch (Exception e) {
                return type.newInstance();
            }
        }
        
        return type.newInstance();
    }

    @SuppressWarnings("unchecked")
    @Override
    protected Class getDefaultType() {
        return Exception.class;
    }

}

 

 

      在使用过程,还发现了另外一个问题,如果在xml里面采用java的转义字符,digester会自动将 代表转义开始的反斜杠("\")进行转义,导致转义字符失效。因为特殊字符也是测试过程中非常用要的 用例,对于这种情况是必须要解决的。

找了半天,用apache commons库里面的StringEscapeUtils进行反转义,来解决这个问题。 用起来非常方便:

if(valueObject instanceof String) {
	valueObject = StringEscapeUtils.unescapeJava((String) valueObject);
}
 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值