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】:如果您在使用MockedStatic
或Mockito.mockStatic
时遇到此异常,也可能意味着您在调用静态方法时混合了匹配器和文字。
尝试将YourClass.staticMethod(any(), "literal")
等任何组合更改为YourClass.staticMethod(any(), eq("literal"))
【讨论】:
以上是关于Mockito 异常 - when() 需要一个参数,该参数必须是模拟上的方法调用的主要内容,如果未能解决你的问题,请参考以下文章