【问题标题】:How to mock super method call如何模拟超级方法调用
【发布时间】:2018-02-05 20:50:19
【问题描述】:

我扩展了一个方法并尝试测试子方法,但是有一个对被覆盖方法的调用,我不知道如何模拟。

public class Parent()
{
    public String foo()
    {
        //Various checks and validation

        if(successful)
        {
            return null;
        }
        else
        {
            return "error";
        }
    }
}

public class Child()
{
    boolean someVariableSetElseWhere;

    @Override
    public String foo()
    {
        String error = super.foo();

        if(error == null && someVariableSetElseWhere)
        {
            //do some other checks
            error = bar();
        }

        return error;
    }
}

我想检查someVariableSetElseWhere 处于不同状态时是否调用bar(),但我总是从super.foo() 得到"error",所以if 语句总是错误的。有没有办法模拟超类返回null。

我试过了

Child mock = Mockito.mock(Child.class);
Mockito.when((Parent)mock.foo()).thenReturn(null);

在我的测试中,但 Child.foo() 每次都返回 null

【问题讨论】:

  • 您的示例应该清楚地表明Child extends Parent 并且可能有助于更正您的类定义的语法。此外,嘲笑一个超级电话是一个坏主意。如果覆盖方法的结果应该依赖于 super,那么以集成方式对其进行测试(否则您测试的是 mock,而不是您的代码)。如果被覆盖方法的结果不应该依赖于 super,那么不要调用 super 并从 super 方法复制代码。在这两种情况下,您都不需要模拟。

标签: java unit-testing mocking mockito


【解决方案1】:

您不要将mock() 与被测代码一起使用,而是将spy() 与具体实例一起使用:

子剪辑 = Mockito.spy(new Child());

但这适用于在Child 类中重写的方法,因为spy() 只是简单地包装剪切并使用常规多态性拦截方法调用。

不要模拟或窥探您的被测代码

  1. UnitTest 验证一个单元的公共可观察行为,并且由于Child 扩展了Parent,我认为它们是一个“单元”。在这种情况下,super.foo() 的调用是一个实现细节你不应该被测试。

  2. 如果您认为 ChildParent 是单独的单元,您还应该考虑应用 Favor Composition over Inheritance 并将实例 ob Parent 注入 Child(最好通过构造函数参数)而不是让Child 扩展Parent。这使得用测试替身替换Parent 变得更加容易。

【讨论】:

  • 使用spy 将无法测试超级调用。 when(cut.foo()) 不会改变Parent.foo 的结果,而是Child.foo 的结果。我同意你的其他建议。
猜你喜欢
  • 1970-01-01
  • 2018-10-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多