bharathp
bharathp

Reputation: 395

Powermockito : java.lang.IllegalArgumentException: argument type mismatch

I don't have much experience with Mocking, I have recently started using it in my Junit test cases. However, I am having difficulties understanding the execution.

I am getting IllegalArgumentException when I try this code

PowerMockito.doNothing().when(spyObject, "lockUser", String.class, User.class);

But when I provide the values that the lockUser would recieve at the time of execution, everything works as expected.

Working code

PowerMockito.doNothing().when(spyObject, "lockUser", "my_text", userMock);

I am rather confused with this behavior. I was expecting identical behaviour. Could someone explain why this is happening ?

In addition when I have the following code

PowerMockito.doNothing().when(spyObject, "lockUser", anyString(), anyObject());

The method is no longer mocked and the real method is invoked.

Interestingly I have another method with same name "lockUser" which takes different number of parameters. And in my other test method, I have used only Matchers (anyObject(), anyString() etc) and that works as expected.

PowerMockito.doNothing().when(spyObject, "lockUser", anyObject(), anyString(), anyString(), anyString());

All lockUser methods are priavate.

I am working with Mockito 1.9.5 together with PowerMock 1.5.6

Any help is greatly appreciated

Edit Additional Code to make it clear

Class Core {
public Worker getWorker(String workerId) {
  // Get worker from Map<String, Worker> fID_WRK with workerId as key 
  // Get user from worker (I have mocked this part, so my mock user is     
  //   returned)
  If(user.isTooOld()) {
   lockUserAndNotify(reason, user);
   throw new UserLockedException("Too old");
   }

private void lockUserAndNotify(String reason, User user) {
  lockUserAndNotify(reason, user.fname, user.lname); // locks user and notifies
}

public getUser(String login, String password) {
  // find user in database
  if(user password is too old) {
    lockUserAndNotify(dbConnection, fname, lname, userId);
  }
}

private lockUserAndNotify(Connection dbConn, String fName, String lName, String
                 userId) {
  //method call to lock the user
  //method call to notify the admin
}


}

My Test class

Class CoreTest {
  @Test (expected = UserLockedException.class)
  public void getUser_ThrowsException() throws                  
             Exception{

    Core core = new Core();
    Core coreSpy = PowerMockito.spy(core);

    when(userMock.isPwdUpdateTimeExpired()).thenReturn(true);
    PowerMockito.doNothing().when(coreSpy, "lockUserAndNotify", 
     anyObject(), anyString(), anyString(), anyString(), anyString());

    admin4.UserManager.getUser("l.user1","password");

  }

@Test (expected = UserLockedException.class)
      public void getWorker_ThrowsException() throws                  
                 Exception{

        Core core = new Core();
        Core coreSpy = PowerMockito.spy(core);

        Map workerMap = Whitebox.getInternalState(coreSpy, "fID_WRK");
        Map workerMapSpy = PowerMockito.spy(workerMap);

        when(workerMapSpy.getWorker("12345")).thenReturn(workerMock);
        when(workerMock.getUser()).thenReturn(userMock);
        when(userMock.isTooOld()).thenReturn(true);
        PowerMockito.doNothing().when(coreSpy, "lockUserAndNotify", 
         anyString(), anyObject());

        admin4.UserManager.getWorker("123445");

      }
}

So the test getUser_ThrowsException works as expected, but getWorker_ThrowsException does not.

Upvotes: 2

Views: 4357

Answers (1)

nikhil
nikhil

Reputation: 9385

To answer the part of your question about IllegalArgumentException: argument type mismatch, you get this because you're using the API incorrectly when you use

PowerMockito.doNothing().when(spyObject, "lockUser", String.class, User.class);

See the documentation of PowerMocktioStubber.when, relevant section reproduced here -

public static <T> org.mockito.stubbing.OngoingStubbing<T> when(Class<?> klass,
                                                               Object... arguments)
                                                        throws Exception

Expect calls to private static methods without having to specify the method name. The method will be looked up using the parameter types if possible

Throws:
    Exception - If something unexpected goes wrong.
See Also:
    Mockito#when(Object)} 

As you've already observed you can use either the values of the real parameters or your can use Matchers like anyString.

Here's some sample code to demonstrate this -

public class Core {
    public String getWorker(String workerId) {
        if (workerId.isEmpty()) {
            lockUser("Reason", workerId);
        }
        return workerId;
    }

    private void lockUser(String reason, String user) {
    }
}

and the corresponding tests -

@RunWith(PowerMockRunner.class)
@PrepareForTest(Core.class)
public class CoreTest {

    @Test
    // this is incorrect usage and throws an IllegalArgumentException
    public void test1() throws Exception {
        Core spy = PowerMockito.spy(new Core());
        PowerMockito.doNothing().when(spy, "lockUser", String.class, String.class);
        spy.getWorker("");
    }

    @Test
    public void test2() throws Exception {
        Core spy = PowerMockito.spy(new Core());
        PowerMockito.doNothing().when(spy, "lockUser", Mockito.anyString(), Mockito.anyString());
        spy.getWorker("");
        PowerMockito.verifyPrivate(spy).invoke("lockUser", Mockito.anyString(), Mockito.anyString());
    }

    @Test
    public void test3() throws Exception {
        Core spy = PowerMockito.spy(new Core());
        PowerMockito.doNothing().when(spy, "lockUser", "abc", "Reason");
        spy.getWorker("abc");
        PowerMockito.verifyPrivate(spy, Mockito.times(0)).invoke("lockUser", Mockito.anyString(), Mockito.anyString());
    }
}

Without compilable code or the exception that you get for getWorker_ThrowsException, it's not possible to answer why that doesn't work as expected. I can take a look again once you add the required information.

Upvotes: 2

Related Questions