首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >自动委托实现方法

自动委托实现方法
EN

Stack Overflow用户
提问于 2019-03-26 23:53:46
回答 1查看 292关注 0票数 0

我可以自动将所有调用委托给共享相同接口的另一个实例的方法吗?

我有一个很大的类(我想测试),如下所示:

代码语言:javascript
复制
class MyClassUnderTest implements SomeInterface {
  public void anImportantMethod() {
  }
  @Override
  public void fromTheInterface() {
  }
  @Override
  public void fromTheInterface2() {
  }
  private void utilFunc() {}
}

它实现了一个接口

代码语言:javascript
复制
interface SomeInterface {
  void fromTheInterface();
  void fromTheInterface2();
}

鉴于此,在单元测试期间,我希望“隐藏”从具有不同实现的接口继承的方法。为此,我编写了一个实用程序类

代码语言:javascript
复制
class DebugSomeInterface implements SomeInterface {
  @Override public void fromTheInterface() { log.debug("1"); }
  @Override public void fromTheInterface2() { log.debug("2"); };
}

现在,我需要将所有可能的调用“委派”给该实现。我通过从MyClassUnderTest派生我自己的类,将所有调用都委托给它:

代码语言:javascript
复制
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一样。也许是像这样的

代码语言:javascript
复制
 MyClassUnderTest underTest = new MyClassUnderTest();
 DebugSomeInterface delegated = new DebugSomeInterface();
 MyClassUnderTest instance = mixin(underTest, SomeInterface.class, delegated);

这可能会创建一个“代理”instance,它将所有方法调用从SomeInterface委托给delegated,其余的委托给underTest

在核心Java中有一些代理对象的机制,但我不能把它们都放在一起。

EN

回答 1

Stack Overflow用户

发布于 2019-03-29 20:09:00

你可以这样做:

代码语言:javascript
复制
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());
    }
}

然后像这样使用它:

代码语言:javascript
复制
MyClassUnderTest underTest = new MyClassUnderTest();
DebugSomeInterface delegated = new DebugSomeInterface();
MyClassUnderTest instance = createProxy(underTest, SomeInterface.class, delegated);

这将按你想要的方式工作,但作为免责声明,我认为这不是一个好主意……必须监视被测对象并模拟出被测对象的一小部分应该是一个危险信号……这是不好的做法,你只需要在代码复杂度高于最优的时候做这样的事情,并且你的类的一部分应该被拆分到其他类中。我从来没有遇到过这样的情况,重构我的逻辑不是更好的解决方案……

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55361343

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档