【问题标题】:Mock/Test Super class call in subclass..is it possible?子类中的模拟/测试超级类调用..可能吗?
【发布时间】:2011-12-14 14:17:16
【问题描述】:

我正在寻找一种解决方案来模拟子类 ButtonClicker 中的超级调用。

Class Click {
      public void buttonClick() throws java.lang.Exception { /* compiled code */ }     } 

Class ButtonClicker extends Click { 
    @Override
    public void buttonClick() throws Exception {

        super.buttonClick();
    } }

【问题讨论】:

  • 提问的时候请说的清楚一点。请详细说明....
  • 我想不出模拟 ButtonClicker 的 'buttonClick' 方法不能满足您的需求的用例 - 您能解释一下您的情况吗?

标签: unit-testing seam mockito easymock jmock


【解决方案1】:

使用继承会降低代码的可测试性。考虑用delegation 替换继承并模拟委托。

提取IClicker界面

interface IClicker {
    void buttonClick();
}

Clicker 类中实现IClicker。如果您正在使用第三方代码,请考虑使用Adapter Pattern

重写你的ButtonClicker如下:

class ButtonClicker implements IClicker {
    Clicker delegate;

    ButtonClicker(Clicker delegate) {
        this.delegate = delegate;
    }

    @Override
    public void buttonClick() throws Exception {
        delegate.buttonClick();
    }

}

现在只需将模拟作为构造函数参数传递:

Clicker mock = Mockito.mock(Clicker.class);
// stubbing here
ButtonClicker buttonClicker = new ButtonClicker(mock);

【讨论】:

  • 感谢您放下代码,这是试图测试覆盖的遗留代码,但现在正在考虑对其进行重构,不过还有几个问题。 1. 类 Click 是第三方代码,你能解释一下为什么我应该考虑适配器而不是委托。我看到即使有委托,我只需要修改我的类 ButtonClicker 实现一个接口。 2. ButtonClicker 实际上是一个动作 bean(seam 组件),它直接从 UI 调用,我想知道如何/何时调用一个参数 ButtonClicker 构造函数,以便委托调用 Click 类的方法?
  • 如果您不使用 ButtonClicker 作为 Clicker,您可以跳过提取接口 IClicker
【解决方案2】:

答案是否定的。模拟只是一个微不足道的接口实现。 (我指的是 API 意义上的接口,而不是特定的 Java 关键字意义上的接口。)所以它不知道任何实现细节,比如哪个类实际实现了功能(本质上没有功能)。

您可以在真实对象上创建一个“间谍”,它只允许您模拟某些方法而不模拟其他方法,但这也不会让您只模拟一个类的超级方法,因为您选择的方法是mock 通常由签名选择,子类和超类都是一样的。

【讨论】:

  • 是的,我尝试过ButtonClicker spy = Mockito.spy(new ButtonClicker()); Mockito.doNothing().when((Clicker)spy).buttonClick(); spy.buttonClick();,即使这让我模拟了超级方法调用。
猜你喜欢
  • 2010-10-11
  • 1970-01-01
  • 2018-12-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-01
  • 1970-01-01
  • 2021-03-31
相关资源
最近更新 更多