【问题标题】:Mocking static methods with Powermockito使用 Powermockito 模拟静态方法
【发布时间】:2017-07-17 05:27:00
【问题描述】:

我正在尝试使用PowerMockito 模拟静态方法。我已经参考了各种stackoverflow答案,例如:Mocking static methods with PowerMock and Mockito

但我得到:org.mockito.exceptions.misusing.InvalidUseOfMatchersException: Misplaced argument matcher detected here 异常。 我花了几个小时调试我的代码和谷歌搜索,但无济于事。我在这里错过了什么?

* 注意:我将它作为 testng 测试运行。 *

我在我的代码中添加了 cmets,它可以帮助你理解我想要做什么。

完整的堆栈跟踪是:

 org.mockito.exceptions.misusing.InvalidUseOfMatchersException: 
 Misplaced argument matcher detected here:

 at MyClassTest.testMethod1(MyClassTest.java:24)`

 You cannot use argument matchers outside of verification or stubbing.
 Examples of correct usage of argument matchers: 
    when(mock.get(anyInt())).thenReturn(null);
    doThrow(new RuntimeException()).when(mock).someVoidMethod(anyObject());
    verify(mock).someMethod(contains("foo")) `

 Also, this error might show up because you use argument matchers with methods that cannot be mocked.
 Following methods *cannot* be stubbed/verified: final/private/equals()/hashCode(). 
 Mocking methods declared on non-public parent classes is not supported.`

at MyClassTest.testMethod1(MyClassTest.java:24)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:84)
at org.testng.internal.Invoker.invokeMethod(Invoker.java:714)
at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:901)
at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1231)
at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:127)
at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:111)
at org.testng.TestRunner.privateRun(TestRunner.java:767)
at org.testng.TestRunner.run(TestRunner.java:617)
at org.testng.SuiteRunner.runTest(SuiteRunner.java:348)
at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:343)
at org.testng.SuiteRunner.privateRun(SuiteRunner.java:305)
at org.testng.SuiteRunner.run(SuiteRunner.java:254)
at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:86)
at org.testng.TestNG.runSuitesSequentially(TestNG.java:1224)
at org.testng.TestNG.runSuitesLocally(TestNG.java:1149)
at org.testng.TestNG.run(TestNG.java:1057)
at org.testng.remote.AbstractRemoteTestNG.run(AbstractRemoteTestNG.java:132)
at org.testng.remote.RemoteTestNG.initAndRun(RemoteTestNG.java:230)
at org.testng.remote.RemoteTestNG.main(RemoteTestNG.java:76)

`

下面是我的代码:

测试类

import static org.mockito.Matchers.anyString;
import org.junit.runner.RunWith;
import org.mockito.BDDMockito;
import org.mockito.Mockito;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import org.testng.annotations.Test;

@Test
@RunWith(PowerMockRunner.class)
@PrepareForTest(AnotherClass.class)
public class MyClassTest {

    MyClass myClass;

    @Test
    public void testMethod1() {

        /*
         * Mock static methods
         */
        PowerMockito.mockStatic(AnotherClass.class);
        BDDMockito.given(AnotherClass.yetAnotherMethod(anyString())).willReturn(Mockito.mock(String.class));

        // call the method of system under test
        myClass.method1();

        // verify
        PowerMockito.verifyStatic();
    }

}

被测系统:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

public class MyClass {

    public String method1() {
        String result = AnotherClass.yetAnotherMethod("Pramithas");
        return result;
    }
}

AnotherClass.java:

import org.springframework.stereotype.Service;

public class AnotherClass {

    public static String yetAnotherMethod(String s) {
        return s;
    }
}

【问题讨论】:

  • 嗯,我面临一个不同的例外。您使用的是哪个版本的 Mockito?您是否尝试将..willReturn(Mockito.mock(String.class)); 替换为..willReturn(Mockito.mock("Hello"));?我认为 Mockito 默认情况下不会模拟最终类。
  • 是的,我尝试使用 .willReturn("Hello");但同样的错误仍然存​​在
  • 哦忘了说我把AnotherClass.class加到PrepareForTest,因为我有一个org.powermock.api.mockito.ClassNotPreparedException
  • 是的,你是对的......我需要将 AnotherClass.class 添加到 PrepareForTest ......但我仍然遇到同样的错误......上述代码是否在您的工作区中成功运行?
  • 提示:与其花费数小时来修复 PowerMock(ito) - 为什么不简单地将静态方法封装在某个接口中 - 并创建一个可以在 没有 PowerMock 的情况下进行测试的更简洁的设计(伊藤)?!

标签: unit-testing junit mockito testng powermockito


【解决方案1】:
  1. 你还没有为MyClass创建新对象
  2. 不要尝试模拟原始类型或最终类
  3. 移除@Test注解

    import org.junit.Test;
    import org.junit.runner.RunWith;
    import static org.mockito.Matchers.anyString;
    import org.mockito.BDDMockito;
    import org.powermock.api.mockito.PowerMockito;
    import org.powermock.core.classloader.annotations.PrepareForTest;
    import org.powermock.modules.junit4.PowerMockRunner;
    
    @RunWith(PowerMockRunner.class)
    @PrepareForTest(AnotherClass.class)
    public class MyClassTest {`
    
      MyClass myClass = new MyClass();
    
     @Test
     public void testMethod1() {
    
       /*
        * Mock static methods
        */
       PowerMockito.mockStatic(AnotherClass.class);
    BDDMockito.given(AnotherClass.yetAnotherMethod(anyString())).willReturn("any String");    
    
       // call the method of system under test
       myClass.method1();
    
       // verify
       PowerMockito.verifyStatic();
     }
    }
    

这是经过验证的。它应该可以工作。

【讨论】:

  • 嗨,Anupama,我很抱歉。但我正在尝试将其作为 testng 测试运行。
  • 以为是误加了。如有错误请更正并回帖
  • 我遇到了同样的错误。错误在 BDDMockito.given(AnotherClass.yetAnotherMethod(anyString())).willReturn("any String");
  • 为什么要作为TestNg运行它?有什么具体原因吗?
  • 您的第二个声明是错误的。整个想法是 PowerMock 创建 不同 字节码。模拟的课程是否是最终课程并不重要。因为它的字节码基本上被丢弃了,取而代之的是 PowerMock(ito) 生成的用于执行其黑魔法的东西。
【解决方案2】:

我让您的示例进行了一些更改:

@RunWith(PowerMockRunner.class)
@PrepareForTest({ AnotherClass.class })
public class MyClassTest {

@Before
public void setUp() {
  myClass = new MyClass();
}

@Test
public void testMethod1() {

/*
 * Mock static methods
 */
PowerMockito.mockStatic(AnotherClass.class);
BDDMockito.given(AnotherClass.yetAnotherMethod(Mockito.anyString())).willReturn("Hello");

// call the method of system under test
String a = myClass.method1();

// verify
PowerMockito.verifyStatic();
}

我也将AnotherClass 添加到PrepareForTest 并强制AnotherClass 模拟返回String 值,因为Mockito 无法模拟最终类,我可以检查myClass 的行为是否符合预期。这是我的 Mockito 和 Powermock 依赖项:

<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-core</artifactId>
    <version>2.7.5</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.powermock</groupId>
    <artifactId>powermock-module-junit4</artifactId>
    <version>1.7.0RC2</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.powermock</groupId>
    <artifactId>powermock-api-mockito2</artifactId>
    <version>1.7.0RC2</version>
    <scope>test</scope>
</dependency>

【讨论】:

  • @PrepareForTest下不用添加测试类(MyClass.class)
  • 是的。这是一个错误的印刷,我会更新我的答案谢谢!
  • 您是否将其作为 testng 测试运行?我正在尝试将其作为 testng 测试运行。对不起,我应该早点提到它。
  • @hermit 如果您将其作为 junit 测试运行会怎样?有用吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-03-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多