spring不仅为我们提供了很方便的代码架构,而且在测试方面,也提供了很多可以参考的规范。下文就spring-test.3.11.jar为例,简单说明在mvc开发中的一种测试技巧。
1.将spring-test与junit结合
@RunWith(value = SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:applicationContext-test.xml" })
作为测试类的注解,就可以引入spring-test和junit了。
2.将controller配置到applicationContext-test.xml中去
因为依赖注入的关系,controller的类中有不少Service的变量,所以不能使用new。
这样,就建立了spring的容器,可以通过controller.method的方式来调用某个方法。
3.controller的方法的初始化。
controller方法的参数,在springmvc主要使用的是有pathvariable,parameter这些简单类型,直接初始化就OK了,比较复杂的是一般由web容器来生成的sevlet的接口实现类,比如ServletRequest接口和ServletResponse接口,不同的web容易的实现类会有所差距,但是基本上都是比较复杂的实现类,一个实现类中会引入很多相关的接口和实现类。
而spring-test 主要提供了MockHttpServletRequest和MockHttpServletResponse这些比较简单的标准的java-bean结构的实现类。
使用的时候,只需要先new这些实现类,然后设置参数即可。
当然,值得一体的是在实现原有的servlet规范中的接口之外,还追加了不少接口,用于设置参数。其实从设计模式上来说,就是简化了原本的web容器的设计模式,如代理模式,builder模式。
4.而且对于spring的一个上传文件的特殊的request的接口MultipartHttpServletRequest的实现类MockMultipartHttpServletRequest
可以在本地直接使用junit来进行上传测试。这时你会发现,上传文件,如此简单。。。
当然,对于下载文件也同样简单了。。。。
5.mock是一种思想,我们也可以对spring-test的mock类进行扩展。
比如MockHttpServletRequest的setQueryString方法就过于简单,可以用这样的代码来进行扩展,就让你感觉到你好像是在浏览器中键入一般,是不是很方便。
public void setQueryString(String queryStr)
{
String[] key_vals = queryStr.split("&");
String key = null; String value = null;
for (String key_val : key_vals) {
String[] temp_key_val = key_val.split("=");
switch (temp_key_val.length)
{
case 1:
key = temp_key_val[0];
value = "";
break;
case 2:
default:
key = temp_key_val[0];
value = temp_key_val[1];
}
try
{
setParameter(key, URLDecoder.decode(value, getCharacterEncoding()));
} catch (UnsupportedEncodingException e) {
setParameter(key, value);
}
}
}
当然,这些都是我在做web项目时候的经验 ,对于本地应用的项目,我想也是可以有很多类似的解决方式的。