我可以自动将所有调用委托给共享相同接口的另一个实例的方法吗?
我有一个很大的类(我想测试),如下所示:
class MyClassUnderTest implements SomeInterface {
public void anImportantMethod() {
}
@Override
public void fromTheInterface() {
}
@Override
public void fromTheInterface2() {
}
private void utilFunc() {}
}它实现了一个接口
interface SomeInterface {
void fromTheInterface();
void fromTheInterface2();
}鉴于此,在单元测试期间,我希望“隐藏”从具有不同实现的接口继承的方法。为此,我编写了一个实用程序类
class DebugSomeInterface implements SomeInterface {
@Override public void fromTheInterface() { log.debug("1"); }
@Override public void fromTheInterface2() { log.debug("2"); };
}现在,我需要将所有可能的调用“委派”给该实现。我通过从MyClassUnderTest派生我自己的类,将所有调用都委托给它:
class MyClassUnderTest_Mock extends MyClassUnderTest {
DebugSomeInterface delegated = new DebugSomeInterface();
@Override public void fromTheInterface() {
delegated.fromTheInterface();
}
@Override public void fromTheInterface2() {
delegated.fromTheInterface2();
};只是,我有很多实现SomeInterface的类,手工实现它既繁琐又容易出错。
我想要一种(半)自动化的方式来创建MyClassUnderTest_Mock实例,就像mock(...)和Mockito一样。也许是像这样的
MyClassUnderTest underTest = new MyClassUnderTest();
DebugSomeInterface delegated = new DebugSomeInterface();
MyClassUnderTest instance = mixin(underTest, SomeInterface.class, delegated);这可能会创建一个“代理”instance,它将所有方法调用从SomeInterface委托给delegated,其余的委托给underTest。
在核心Java中有一些代理对象的机制,但我不能把它们都放在一起。
发布于 2019-03-29 20:09:00
你可以这样做:
public static <T, U extends T> U createProxy(U classUnderTest, Class<T> interfaceType, T debugImplementation)
throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
U spy = Mockito.spy(classUnderTest);
for (Method m : interfaceType.getMethods()) {
Object[] params = new Object[m.getParameterTypes().length];
for (int i = 0; i < params.length; i++) {
params[i] = Mockito.any();
}
Mockito.when(m.invoke(spy, params)).thenAnswer(new Delegate(debugImplementation, m));
}
return spy;
}
public static class Delegate implements Answer {
private final Object delegate;
private final Method delegateMethod;
public Delegate(Object delegate, Method delegateMethod) {
this.delegate = delegate;
this.delegateMethod = delegateMethod;
}
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
return delegateMethod.invoke(delegate, invocation.getArguments());
}
}然后像这样使用它:
MyClassUnderTest underTest = new MyClassUnderTest();
DebugSomeInterface delegated = new DebugSomeInterface();
MyClassUnderTest instance = createProxy(underTest, SomeInterface.class, delegated);这将按你想要的方式工作,但作为免责声明,我认为这不是一个好主意……必须监视被测对象并模拟出被测对象的一小部分应该是一个危险信号……这是不好的做法,你只需要在代码复杂度高于最优的时候做这样的事情,并且你的类的一部分应该被拆分到其他类中。我从来没有遇到过这样的情况,重构我的逻辑不是更好的解决方案……
https://stackoverflow.com/questions/55361343
复制相似问题