一尘不染

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

java

我在某些测试中使用Mockito。

我有以下课程:

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

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

我只想模拟的第二个调用(super.save)ChildService。第一次调用必须调用real方法。有没有办法做到这一点?


阅读 975

收藏
2020-03-11

共2个答案

一尘不染

Mockito不支持此功能。

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

偏重于继承而不是继承

如果你提取策略而不是扩展超类,那么问题就不存在了。

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

我建议你进行重构,但是如果这不是一种选择,那么你将获得一些严肃的黑客乐趣。

2020-03-11
一尘不染

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

    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();
    }
2020-03-11