Mockito - 模拟基础实现同时测试相同方法的派生类实现

时间:2014-04-21 11:26:46

标签: java unit-testing mockito

我正在使用Mockito进行一些单元测试。我有以下课程:

public class Base {
    public void say() {
        System.out.println("Base"); // some work in the base class
    }
}

public class Derived extends Base {
    @Override
    public void say() {
        super.say();   // do the base class work
        System.out.println("Derived"); // some additional work in the derived class
    }
}

现在我想在模拟基础say()方法时测试Derived类的say()方法。我按照这里的建议:Mockito How to mock only the call of a method of the superclass我现在有了。

public class DerivedTest {
    @Test
    public void testSay() {
        Derived obj = Mockito.spy(new Derived());
        Mockito.doNothing().when((Base)obj).say();
        obj.say();
        // assert only "Derived" was output
    }
}

但这不起作用,因为它嘲弄基类和派生类实现。我想测试派生类中的额外逻辑。

我该怎么办呢。

更新:我的解决方案

由于我无法按照建议更改基类,因此我修改了派生类以在单独的方法中提取所有额外的逻辑,并且只测试了该方法。

public class Derived extends Base {
    @Override
    public void say() {
        super.say();   // do the base class work
        doAdditionalWork();  // some additional work in the derived class
    }

    void doAdditionalWork() {
        System.out.println("Derived");
    }
}

public class DerivedTest {
    @Test
    public void testDoAdditionalWork() {
        Derived obj = new Derived();
        obj.doAdditionalWork();
        // assert only "Derived" was output
    }
}

这意味着我仍然没有测试派生的say()方法,但鉴于现在的逻辑非常简单,我希望我可以原谅这个。另一个缺点是我不能为doAdditionalWork()方法提供比package-private更严格的可见性。

1 个答案:

答案 0 :(得分:1)

当您spy一个对象时,您完全取代了您为其定义模拟行为的方法的实现。所以,正如你在问题中所指出的那样,这是行不通的。

解决这个问题的一个技巧是提取additionalBehavior()方法,并且只测试它,而不用间谍或嘲笑:

public class Base {
    public void say() {
        System.out.println("Base"); // some work in the base class
        additionalBehavior();
    }

    protected void additionalBehavior() {
        // No implementation. Alternatively - make it abstract
    }
}

public class Derived extends Base {
    @Override
    protected void additionalBehavior() {
        System.out.println("Derived"); // some additional work in the derived class
    }
}

public class DerivedTest {
    @Test
    public void testAdditionalBehavior() {
        Derived obj = new Derived();
        obj.additioanlBehavior();
        // assert that "Derived" was the output
    }
}