我的代码中有几个小技巧,在测试时会引起痛苦。假设将小神打成碎片对于这个练习来说太费力了。
通常的问题是我想测试一个方法x()
,Foo
但是要创建一个实例Foo
,我需要定义 N (1 < N < 10) 个模拟实例,这些实例只是为了满足 Spring 的@Autowire
. 在生产中,我必须确保这些字段是连线的,因此不能选择这些字段。
我看到的可能解决方案:
- 以某种方式告诉 Spring
@Autowire
在测试期间某些字段是可选的 - 为被测代码不需要/不应该需要的任何东西传递不可调用的模拟。
由于我不知道#1 的方法,我认为#2 是要走的路。我更喜欢的是一个 bean 工厂,它返回一个代理,该代理会为我未定义的任何 bean 的任何方法调用引发异常。
所以对于任何未知的bean,它都应该调用这个create
方法:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class MustNotCallMe {
@SuppressWarnings( "unchecked" )
public static <T> T create( final Class<T> type, final Class<?>... types ) {
InvocationHandler handler = new InvocationHandler() {
@Override
public Object invoke( Object proxy, Method method, Object[] args ) throws Throwable {
if( "equals".equals( method.getName() ) && Object.class.equals( method.getDeclaringClass() ) ) {
return proxy == args[0];
}
throw new UnsupportedOperationException( "You must not call " + method );
}
};
Class<?>[] allClasses = new Class<?>[ types.length + 1 ];
allClasses[0] = type;
System.arraycopy( types, 0, allClasses, 1, types.length );
return (T) Proxy.newProxyInstance( MustNotCallMe.class.getClassLoader(), allClasses, handler );
}
}
这样的事情存在吗?如果没有,我将如何在 Spring 3 单元测试中注入我自己的 bean 工厂?
编辑我知道这个想法会让任何语言纯粹主义者感到不安。只有现实很少是纯粹的。如果这里有人愿意站出来为我们提供重构软件所需的资金和人力,我们很乐意听到。在那之前,无需大量手动工作即可解决问题的解决方案可以更好地解决我们的特定问题:-)
也就是说,我所需要的只是一种方法来创建一个BeanFactory
从不抛出NoSuchBeanException
但返回一个“不要打电话给我”的代理。