当前位置: 首页 > 知识库问答 >
问题:

Powermock在最终void方法上意外引发InvalidUseOfMatchersException

郎增
2023-03-14

我正在对我的Java应用程序进行单元测试。。

我的目标是使用Powermock在BOProcessor类的实例上创建一个间谍。BOProcessor拥有最终作废方法;我将设置spy,以便在调用此方法时引发异常。在这个测试中,我还将模拟MyDao,但模拟这个类很简单。然后,模拟的MyDao将被传递到名为classUnderTest的MyDaoService实例中。然后,我将针对classUnderTest做出断言。

每当我尝试设置上述场景时,Powermock(或Mockito?)在我的间谍上设置doThrow时会抛出InvalidUseOfMatchersException。奇怪的是,只有当doThrow期望后跟一个对class UnderTest的调用时,才会抛出此异常。如果我删除稍后调用的class UnderTest,则预期工作正常。更奇怪的是——class UnderTest甚至不使用抛出错误的间谍!

这是我上面概述的全部测试代码。为了突出问题,我删除了所有不直接相关的代码。(我甚至取消了这次测试的全部目的。)

package my.package;

import static org.mockito.Matchers.any;
import static org.mockito.Mockito.doThrow;
import static org.powermock.api.mockito.PowerMockito.mock;
import static org.powermock.api.mockito.PowerMockito.spy;

import org.junit.Test;

public class WhatAmIDoingWrong {

    @Test
    public void whatAmIDoingWrong() {

        MyDao mockedDao = mock(MyDao.class);
        BOProcessor processor = new BOProcessor();
        BOProcessor mockedProcessor = spy(processor);

        MyDaoService classUnderTest = new MyDaoService(mockedDao);

        doThrow(new Exception()).when(mockedProcessor).process(any(FakeBusinessObject.class));

        classUnderTest.interactWithDao();
    }
}

这是从我的测试代码的doThrow行抛出的异常(讽刺的是),我正试图解决它。

org.mockito.exceptions.misusing.InvalidUseOfMatchersException: 
Invalid use of argument matchers!
0 matchers expected, 1 recorded:
-> at my.package.WhatAmIDoingWrong.whatAmIDoingWrong(WhatAmIDoingWrong.java:21)

This exception may occur if matchers are combined with raw values:
    //incorrect:
    someMethod(anyObject(), "raw String");
When using matchers, all arguments have to be provided by matchers.
For example:
    //correct:
    someMethod(anyObject(), eq("String by matcher"));

For more info see javadoc for Matchers class.

    at my.package.MyDaoService.interactWithDao(MyDaoService.java:33)
    at my.package.WhatAmIDoingWrong.whatAmIDoingWrong(WhatAmIDoingWrong.java:23)
    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:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:89)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:41)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:541)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:763)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:463)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:209)

这是我的测试使用的类。重申一下,名为class UnderTest的MyDaoService甚至不知道BOProczer的间谍;它只对MyDao的模拟有效。但是只有调用了类UnderTest,对BOProczer间谍的期望才会失败。

public class BOProcessor {

    public final void process(FakeBusinessObject bar) {}
}
public class FakeBusinessObject {

}
import java.util.Collections;
import java.util.List;

public class MyDao {

    public MyDao() {}

    public List<String> getAllData(){
        return Collections.emptyList();
    }

}
public class MyDaoService {

    private MyDao applicationDao;

    public MyDaoService(MyDao applicationDao) {
        this.applicationDao = applicationDao;
    }

    public synchronized void interactWithDao() {
        applicationDao.getAllData();
    }
}

我使用的是JUnit 4.12、Mockito 1.10.19和Powermock 1.7.4。该项目正在运行Spring 4.3.12版本,包括Spring测试。

为什么Powermock会引发此异常?我是否未正确使用任何匹配器?究竟为什么只有当稍后的调用与不同的模拟交互时才会引发此异常?

谢谢你的帮助!

共有1个答案

蒋鹏鹍
2023-03-14

原来我用间谍是错误的。组织中的某些东西。莫基托。存根。斯塔伯。当(T mock)被实现时,意味着我不能以我想要的方式对间谍设定期望。但无论如何,捕获实际上更适合我的用例。

最后,我的测试是这样的:

public class FixedNow{

    @Test
    public void fixedNow() {

        MyDao mockedDao = mock(MyDao.class);
        BOProcessor mockedProcessor = mock(BOProcessor.class);
        FakeBusinessObject problematicBO = new FakeBusinessObject();
        ArgumentCaptor<FakeBusinessObject> fakeBOCaptor = ArgumentCaptor.forClass(FakeBusinessObject.class);

        MyDaoService classUnderTest = new MyDaoService(mockedDao, mockedProcessor);

        doThrow(new Exception()).when(mockedProcessor).process(eq(problematicBO));
        doNothing().when(mockedProcessor).process(fakeBOCaptor.capture());

        classUnderTest.interactWithDao();

        assertThings(BOCaptor.getValue());
    }
}

谢谢你的想法!

 类似资料:
  • 试图让Mockito和PowerMock正常运行,但在尝试运行以下代码时,我得到了: 而这个IO类 我想要做的是以某种方式触发,以便可以测试。为什么有人会问?我在看我的Jacoco报告,我看到了这个: null

  • 我的进程在linux服务器上被杀,无需人工干预。我已经验证了以下场景。 用户或管理员均未进行手动干预以杀死 该进程占用16.5GB的虚拟内存,其中RAM为16GB,交换为50GB。 任务:总共393个,2个跑步,387个睡觉,4个停止,0个僵尸 Cpu:12.8%us,0.5%sy,0.0%ni,86.7%id,0.0%wa,0.0%hi,0.0%si,0.0%st 内存:总共16015M,使用8

  • 我有一个返回类型为的方法。它还可以抛出许多异常,所以我想测试一下那些被抛出的异常。所有尝试都失败了,原因相同: 类型Stubber中的(T)不适用于参数(void)时的方法 有什么想法,我可以如何获得方法抛出一个指定的异常?

  • 问题内容: 我有一个带有返回类型的方法。它还可以引发许多异常,因此我想测试所引发的异常。所有尝试均以相同的原因失败: Stubber类型中的when(T)方法不适用于参数(void) 有什么想法可以获取引发指定异常的方法吗? 问题答案: 括号放置不正确。 您需要使用: 而 不是 使用: 在文档中对此进行了解释

  • 问题内容: 我创建了一个从API获取URL并返回URL字符串作为结果的函数。但是,Xcode给我此错误消息: void函数中非预期的非无效返回值 有谁知道为什么会这样吗? 问题答案: 使用闭包而不是返回值:

  • 我试图用PowerMock在Mockito上模拟一个静态void方法,但它并不是那么好用。 我的示例代码: EvilBrother.java 我的问题是,嵌套类按照预期的方式使用@PrepareForTest和PowerMockito.MockStatic组合进行了模拟,但是如果类在自己的类文件中,这些语句就不起作用了。 如何修复这个测试? 与 尽管执行了assert.fail,但可以通过Powe