Mockito 如何仅模拟超类的方法的调用

2022-08-31 09:14:16

我在一些测试中使用Mockito。

我有以下类:

class BaseService {  
    public void save() {...}  
}

public Childservice extends BaseService {  
    public void save(){  
        //some code  
        super.save();
    }  
}   

我只想嘲笑 的第二个调用 ()。第一个调用必须调用 real 方法。有没有办法做到这一点?super.saveChildService


答案 1

如果你真的没有重构的选择,你可以模拟/存根超级方法调用中的所有内容,例如

    class BaseService {

        public void validate(){
            fail(" I must not be called");
        }

        public void save(){
            //Save method of super will still be called.
            validate();
        }
    }

    class ChildService extends BaseService{

        public void load(){}

        public void save(){
            super.save();
            load();
        }
    }

    @Test
    public void testSave() {
        ChildService classToTest = Mockito.spy(new ChildService());

        // Prevent/stub logic in super.save()
        Mockito.doNothing().when((BaseService)classToTest).validate();

        // When
        classToTest.save();

        // Then
        verify(classToTest).load();
    }

答案 2

不,Mockito不支持这一点。

这可能不是您要寻找的答案,但是您看到的是不应用设计原则的症状:

支持组合而不是继承

如果你提取一个策略而不是扩展一个超类,问题就消失了。

但是,如果您不被允许更改代码,但无论如何您都必须对其进行测试,并且以这种尴尬的方式,仍然有希望。使用一些AOP工具(例如AspectJ),您可以将代码编织到超类方法中,并完全避免其执行(yuck)。如果您使用的是代理,则这不起作用,您必须使用字节码修改(加载时编织或编译时编织)。也有一些模拟框架支持这种类型的技巧,比如PowerMock和PowerMockito。

我建议你去重构,但如果这不是一个选择,你就会享受一些严肃的黑客乐趣。


推荐