Mockito在尝试在包私有超类上实现的存根方法时调用实际方法

时间:2015-06-03 22:21:50

标签: java mockito

这可能与this question的根本问题相同,但更容易重现。

问题在于在模拟的公共类上存根接口方法,该公共类扩展了具有接口方法实现的包私有类。 Mockito将在包私有类中调用真正的接口方法实现。请参阅以下示例。

接口

public interface DontCallMe {
    int dontCallMeSuper();
    int dontCallMe();
}

包实现其中一个接口方法的默认类。

abstract class PackagePrivate
        implements DontCallMe {

    @Override
    public int dontCallMeSuper() {
        throw new IllegalArgumentException("don't call me super");
    }
}

实现另一个的包私有类的公共子类。

public class Public
    extends PackagePrivate {

    public Public() {
        super();
    }

    @Override
    public int dontCallMe() {
        throw new IllegalArgumentException("don't call me");
    }
}

测试课

import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import org.junit.Test;

public class ExampleJunit {

    @Test
    public void testStaticConstructorInnerClass() {
        final Public comparable = mock(Public.class);
        when(comparable.dontCallMe()).thenReturn(1);
        when(comparable.dontCallMeSuper()).thenReturn(1);
    }
}

运行测试的结果

java.lang.IllegalArgumentException: don't call me super
at PackagePrivate.dontCallMeSuper(PackagePrivate.java:6)
at Public.dontCallMeSuper(Public.java:1)
at ExampleJunit.testStaticConstructorInnerClass(ExampleJunit.java:19)

我可以通过公开PackagePrivate来解决这个问题,但这并不好。有没有办法让我在PackagePrivate类上实现存根方法?

2 个答案:

答案 0 :(得分:1)

您可以模拟界面(DontCallMe)而不是类(Public):

    final DontCallMe comparable = mock(DontCallMe.class);

或者,如果您需要模拟Public但不在DontCallMe中的方法,则可以创建一个新接口并进行模拟。

例如,使用原始DontCallMe定义,您可以执行此操作:

public interface IPackagePrivate extends DontCallMe {
    int extraMethod();
}

------

abstract class PackagePrivate implements IPackagePrivate { 
    public int dontCallMeSuper() { 
        throw new IllegalArgumentException("don't call me super");
    } 
}

------

public class Public extends PackagePrivate { 

    public Public() { 
        super(); 
    } 

    public int dontCallMe() { 
        throw new IllegalArgumentException("don't call me");
    }

    public int extraMethod() { 
        throw new IllegalArgumentException("extra method");
    } 
} 

------

import static org.mockito.Mockito.mock; 
import static org.mockito.Mockito.when; 
import org.junit.Test; 

public class ExampleJunit { 

    @Test
    public void testStaticConstructorInnerClass() { 
        final IPackagePrivate comparable = mock(IPackagePrivate.class);
        when(comparable.dontCallMe()).thenReturn(1);
        when(comparable.dontCallMeSuper()).thenReturn(1);
        when(comparable.extraMethod()).thenReturn(1);
    } 
} 

答案 1 :(得分:1)

做一些谷歌搜索,这是一个已知的mockito bug。见https://github.com/mockito/mockito/issues/168。针对mockito 2.0的https://github.com/mockito/mockito/pull/171中提出的修正