本文介绍了Mockito - 存根抽象父类方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我看到非常奇怪的行为试图存根定义 myMethod(param)的类 MyClass 在抽象父类 MyAbstractBaseClass

I am seeing very strange behavior trying to stub a method myMethod(param) of class MyClass that is defined in an abstract parent class MyAbstractBaseClass.

当我尝试存根时(使用 doReturn( ...)。when(MyClassMock).myMethod(...)等)此方法失败,在不同的场景下抛出不同的异常。异常在该行上抛出。

When I try to stub (using doReturn("...").when(MyClassMock).myMethod(...) etc.) this method fails, different exceptions are thrown under different scenarios. The exceptions are thrown right on that line.

当我使用 doReturn(...)。when(MyClassMock).myMethod(CONCRETE) PARAM CLASS OBJECT),我得到以下异常:

When I use doReturn("...").when(MyClassMock).myMethod(CONCRETE PARAM CLASS OBJECT), I get the following exception:

org.mockito.exceptions.misusing.WrongTypeOfReturnValue:
String cannot be returned by hasValidExpirationDate()
hasValidExpirationDate() should return boolean
    at ...

hasValidExpirationDate()不是一个被存根的方法,但它是由<$ c $的实际实现调用的c>抽象基类中的MyMethod(param)。

hasValidExpirationDate() is not a method being stubbed, but it is called by the real implementation of MyMethod(param) in the abstract base class.

当我使用 doReturn( ...)。当(MyClassMock).myMethod(any(PARAMCLASS.class))时,我得到以下异常:

When I use doReturn("...").when(MyClassMock).myMethod(any(PARAMCLASS.class)), I get the following exception:

org.mockito.exceptions.misusing.InvalidUseOfMatchersException:
Invalid use of argument matchers!
0 matchers expected, 1 recorded.
This exception may occur if matchers are combined with raw values:

等。

但是当我在子类 MyClass myMethod(param)时$ c>代码不再失败。我在 MyClass 中的具体实现只是调用 super.myMethod(param)并返回它,所以它除了修理单元测试。所以看起来Mockito只能在类中定义的存根方法被自己模拟,而不是在超类中。

But when I define the method myMethod(param) in a subclass MyClass the code no longer fails. My concrete implementation in MyClass just calls super.myMethod(param) and returns it, so it has no effect other than fixing the unit test. So it looks like Mockito can only stub methods defined in the class being mocked itself, not in the super classes.

我正在阅读Mockito文档而我看不到哪里它说继承的方法不能被存根。

I am reading Mockito documentation and I don't see where it says that inherited methods can't be stubbed.

myMethod(param)既不是 static 也不是 final

Class BaseCard

import java.io.Serializable;

public class BaseCard implements Serializable {

    public boolean hasValidExpirationDate() {
        return true;
    }
}

Class

abstract class Card  extends BaseCard {

    public Card () {    }

    public String getUnexpiredStringForNetwork(){

        //If the date is invalid return empty string, except for Discover.
        if( ! hasValidExpirationDate()){
           return "hi";
        }

        return "hello";
    }
}

Class DecryptedCard

public class DecryptedCard extends Card {

}

Class MyTest

import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;

import org.junit.Test;


public class MyTest {

    @Test
    public void test() {
        DecryptedCard decryptedCardMock = mock(DecryptedCard.class);

        doReturn("ABC").when(decryptedCardMock).getUnexpiredStringForNetwork();

    }

}

失败:

org.mockito.exceptions.misusing.WrongTypeOfReturnValue:
String cannot be returned by hasValidExpirationDate()
hasValidExpirationDate() should return boolean
***
If you're unsure why you're getting above error read on.
Due to the nature of the syntax above problem might occur because:
1. This exception *might* occur in wrongly written multi-threaded tests.
   Please refer to Mockito FAQ on limitations of concurrency testing.
2. A spy is stubbed using when(spy.foo()).then() syntax. It is safer to stub spies -
   - with doReturn|Throw() family of methods. More in javadocs for Mockito.spy() method.

    at Card.getUnexpiredStringForNetwork(Card.java:10)
    at DecryptedCard.getUnexpiredStringForNetwork(DecryptedCard.java:1)
    at MyTest.test(MyTest.java:13)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:45)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:263)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:68)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:47)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:300)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)


推荐答案

根据,当父类非公开时,无法保证模拟行为,如。

According to this SO answer, mock behavior isn't guaranteed when parent class is non-public, as documented in issue 212.

(感谢Brice的好处回答另一个帖子,感谢Vladimir,JB Nizet和acdcjunior在评论主题中共享调试进度!)

(Thanks Brice for the good answer in the other thread, and thanks Vladimir, JB Nizet, and acdcjunior for sharing debugging progress in the comments thread!)

这篇关于Mockito - 存根抽象父类方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-29 21:06
查看更多