Mockito 异常 - when() 需要一个参数,该参数必须是模拟上的方法调用

Posted

技术标签:

【中文标题】Mockito 异常 - when() 需要一个参数,该参数必须是模拟上的方法调用【英文标题】:Mockito Exception - when() requires an argument which has to be a method call on a mock 【发布时间】:2012-02-29 11:48:08 【问题描述】:

我有一个使用 Mockito 和 Spring Test 框架的非常简单的测试用例。当我这样做时

when(pcUserService.read("1")).thenReturn(pcUser);

我得到了这个例外。

org.mockito.exceptions.misusing.MissingMethodInvocationException: 
when() requires an argument which has to be 'a method call on a mock'.
For example:
    when(mock.getArticles()).thenReturn(articles);

Also, this error might show up because:
1. you stub either of: final/private/equals()/hashCode() methods.
   Those methods *cannot* be stubbed/verified.
2. inside when() you don't call method on mock but on some other object.

    at com.project.cleaner.controller.test.PcUserControllerTest.shouldGetPcUser(PcUserControllerTest.java:93)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)

我尝试了不同的方法,但不断收到此错误消息。我正在使用带有 Mockito 的 Spring 3.1.0.RELEASE。请分享并指导我正确的方向。

【问题讨论】:

我有同样的问题,但我正在使用:@Autowired @ReplaceWithMock(beanName="logDao") private LogDao logDaoMock; 【参考方案1】:

您需要先创建一个 pcUserService 的 MOCK,然后使用该模拟。

PcUserService mock = org.mockito.Mockito.mock(PcUserService.class);
when(mock.read("1")).thenReturn(pcUser);

【讨论】:

但在这种情况下我无法调试。它真的调用了那个方法吗? @eatSleepCode:在这个例子中,REAL 方法PcUserService.read 永远不会被调用。相反,一个 Mockito Mock 被调用,这个模拟返回 pcUser 是的,我遇到了这个问题,我有一个服务,比如说TestService,它有一个方法testMethod()testMethod 中的代码包括调用另一个服务方法,例如。 AnotherTestService.getData()。所以在我的情况下,我无法模拟 AnotherTestService 我该怎么办? 为什么不能用模拟替换AnotherTestService @eatSleepCode:也许你应该看看这个答案:***.com/a/20856647/280244【参考方案2】:

如果其他人遇到这个问题......

您尝试模拟的方法pcUserService.read 也可能被声明为final 方法。据我所知,这似乎会导致 Mockito 出现问题。

【讨论】:

诊断没问题,但有什么解决办法:p @amdev 不要将pcUserService.read 设为final :) 我知道这并不理想,但您无能为力。 Mockito 无法模拟最终方法。有关更多详细信息和可能的解决方法,请参阅***.com/questions/3793791/final-method-mocking 实际上,有时您不会模拟自己的类,而是模拟来自外部依赖项的某个类。但没关系,我找到了如何使用 mockito ***.com/questions/14292863/… 模拟最终方法【参考方案3】:

此问题的另一个解决方案可能是,如果测试类使用PowerMockRunner,您可能必须在@PrepareForTest 注释中将要模拟的类添加到列表中。

例如-

@PrepareForTest( PcUserService.class )

【讨论】:

谢谢,我以为我有,但我实际上将接口添加到@preparefortest 列表,而不是类,这个答案让我在那里仔细检查。【参考方案4】:

这种错误还有另一个可能的原因 - 有时 IDE 更喜欢从另一个包中静态导入 Mockito.when():

import static io.codearte.catchexception.shade.mockito.Mockito.when;

import static org.mockito.Mockito.when; //should normally use this one

问题是 io.codearte 包中的“何时”在编译级别与 org.mockito.Mockito.any() 兼容,但在运行时失败并显示完全相同的错误消息。

【讨论】:

【参考方案5】:

如果你使用Kotlin,你应该知道方法默认是final。所以写open fun而不是fun。感谢@djkelly99 的提示。

【讨论】:

感谢这项工作。但是1个问题。如果不将方法和类设置为open,我将如何解决此问题 @viper,谢谢!我现在不使用测试,但假设你应该使用这个库的更新版本。如果我没记错的话,它支持final 方法。或许你可以尝试创建接口或抽象类。 我有最新版本的mockito,但我仍然遇到问题。使用open 修饰符有什么缺点? @viper,见***.com/questions/14292863/…,github.com/mockito/mockito/wiki/What%27s-new-in-Mockito-2,github.com/powermock/powermock/wiki/mockito。 @viper,这意味着您的 open 类的后代可能会以您意想不到的方式改变行为。重写的方法可以访问您不想访问的那些集合。甚至更改集合、对象。另见quora.com/What-are-all-the-advantages-of-inheritance-in-Java、quora.com/What-are-the-disadvantages-of-inheritance-in-Java。【参考方案6】:

我有同样的问题,我试图模拟它的方法是最终方法。我删除了修饰符,它工作正常。

【讨论】:

【参考方案7】:

为了帮助遇到同样问题的其他人;

您尝试模拟的方法 pcUserService.read 被声明为 final 方法。静态方法似乎会导致 Mockito 出现问题。

【讨论】:

【参考方案8】:

基本上,您需要使用 PowerMockito.mockStatic 为类的所有静态方法启用静态模拟。这意味着可以使用 when-thenReturn 语法对它们进行存根。 例如: PowerMockito.mockStatic(TestClass.class); when(TestClass.getString()).thenReturn("HelloWorld!"); 注意:您必须将@PrepareForTest( TestClass.class ) 添加到您的单元测试类中。

【讨论】:

【参考方案9】:

在我的情况下,它是通过注入 @MockBean 解决的。

例如

@MockBean
StateRepository mockStateRepository;

【讨论】:

【参考方案10】:

如果您使用 KOIN,请在 gradle 的依赖项中包含:

dependencies 
    ...
    testImplementation "org.koin:koin-test:2.0.0"

【讨论】:

【参考方案11】:

在模拟另一个类的静态方法时,我在测试 someClass 的方法时遇到了类似的问题。在这种情况下,我们需要添加 @PrepareForTest(anotherClass.class, someClass.class) 具有静态方法的类和调用者类。

【讨论】:

【参考方案12】:

如果您在使用MockedStaticMockito.mockStatic 时遇到此异常,也可能意味着您在调用静态方法时混合了匹配器和文字。

尝试将YourClass.staticMethod(any(), "literal") 等任何组合更改为YourClass.staticMethod(any(), eq("literal"))

【讨论】:

以上是关于Mockito 异常 - when() 需要一个参数,该参数必须是模拟上的方法调用的主要内容,如果未能解决你的问题,请参考以下文章

mockito 无返回值方法及异常mock

mockito 无返回值方法及异常mock

mockito 无返回值方法及异常mock

Mockito - JUnit + Mockito 单元测试之打桩 when().thenReturn()

mockito when() 调用如何工作?

Mockito.when评估表达式