1

I am trying to mock static method with PowerMockito. I have referred to various stackoverflow answers such as this:Mocking static methods with PowerMock and Mockito

But I am getting : org.mockito.exceptions.misusing.InvalidUseOfMatchersException: Misplaced argument matcher detected here exception. I have spent hours debugging my code and google searching but to no avail. What am I missing here?

* Note: I am running it as a testng test. *

I have added comments in my code that may help you understand what I am trying to do.

The full stack trace is:

 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)

`

Below is my code:

Test Class

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();
    }

}

System Under Test:

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;
    }
}
hermit
  • 1,048
  • 1
  • 6
  • 16
  • Uhm I am facing a different exception. Which version of Mockito are you using? Did you try to substitute `..willReturn(Mockito.mock(String.class));` with `..willReturn(Mockito.mock("Hello"));`? I think Mockito does not mock final classes by default. – Francesco Jul 17 '17 at 06:29
  • Yes I tried with .willReturn("Hello"); But same error persists – hermit Jul 17 '17 at 06:32
  • oh forgot to mention I add `AnotherClass.class` to `PrepareForTest` because I got a `org.powermock.api.mockito.ClassNotPreparedException`. – Francesco Jul 17 '17 at 06:43
  • Yes you are right... I needed to add AnotherClass.class to PrepareForTest...But I am still gettng the same error.. Does the above code run successfully in your workspace? – hermit Jul 17 '17 at 06:45
  • Yes. I change the `..(Mockito.mock(String.class))..` with a string and I also have to instantiate a `MyClass` object (`myClass = new MyClass();`) to prevent a `NPE` but this is surely driven by different environments. – Francesco Jul 17 '17 at 06:49
  • Share your Mockito and Powermock versions. – Francesco Jul 17 '17 at 07:08
  • 1
    Hint: instead of spending hours to fix PowerMock(ito) - why not simply encapsulate that static method in some interface - and create a cleaner design that can be tested **without** PowerMock(ito)?! – GhostCat Jul 17 '17 at 10:14
  • @GhostCat thank you for the suggestion.. – hermit Jul 27 '17 at 07:05

2 Answers2

1
  1. You haven't created new object for MyClass
  2. Do not try to mock primitive types or final classes
  3. Removed @Test annotation

    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();
     }
    }
    

This is verified. It should work.

Anupama Boorlagadda
  • 1,158
  • 1
  • 11
  • 19
  • Hi Anupama, my apologies. But I am trying to run it as a testng test. – hermit Jul 17 '17 at 07:56
  • Thought it was added by mistake. Please correct it and post back in case of failure – Anupama Boorlagadda Jul 17 '17 at 08:03
  • I am getting the same error. The error is in the line BDDMockito.given(AnotherClass.yetAnotherMethod(anyString())).willReturn("any String"); – hermit Jul 17 '17 at 08:03
  • Why do you want to run it as TestNg? Any specific reason? – Anupama Boorlagadda Jul 17 '17 at 08:07
  • Your second claim is wrong. The whole idea is that PowerMock creates **different** bytecode. It doesn't matter at all if the mocked class is final. Because its bytecode is basically thrown away and replaced with something that PowerMock(ito) generated to do its black magic. – GhostCat Jul 17 '17 at 10:13
  • @GhostCat In general when you try to mock final classes junit would throw an exception saying you cannot mock final classes. Please correct me if I am wrong. – Anupama Boorlagadda Jul 17 '17 at 11:28
  • That is with EasyMock or Mockito. I created an [example](https://stackoverflow.com/questions/45034464/powermock-static-final-method-in-final-class/45034591#45034591) last week where I mock a final class. Again: PowerMock throws away the existing bytecode for the "prepared" class and creates its **own** bytecode. It doesn't matter if the original class said "final" - because powermock replaces that with something else. That is btw why I avoid using PowerMock. – GhostCat Jul 17 '17 at 11:31
  • @GhostCat Thanks for that! I tried to give some tip on this, As far as I know, it is a bad practice to mock final class. Since the code posted in the question is mocking a final class, I gave a tip. If it is good to mock a final class, do say, I will edit my answer – Anupama Boorlagadda Jul 17 '17 at 11:40
  • You are getting things wrong here. The point is that most mocking framework (imho: all the reasonable ones that I would recommend using) do not allow for mocking final elements. In that sense: if you intend to mock something, then you decided that you want to mock that thing. And in case you like the answer I linked over there, feel free to upvote that answer ;-) – GhostCat Jul 17 '17 at 13:23
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/149437/discussion-between-anupama-boorlagadda-and-ghostcat). – Anupama Boorlagadda Jul 18 '17 at 05:59
0

I got your example working with some changes:

@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();
}

I added AnotherClass to PrepareForTest too and I force AnotherClass mock to return a String value because Mockito can't mock final classes and I can check that myClass behave as expected. Here is my Mockito and Powermock dependencies:

<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>
Francesco
  • 1,742
  • 5
  • 44
  • 78