PowerMockito calls real method on Mocked Object when defining second "when" clause

741 views Asked by At

I am trying to define some different mocked behaviours when a method is called with different parameters. Unfortunately, I find that the second time I try to mock the given method on a (mocked) class, it runs the actual method, causing an exception because the matchers are not valid parameters. Anyone know how I can prevent this?

    manager = PowerMockito.mock(Manager.class);
    try {
        PowerMockito.whenNew(Manager.class).withArguments(anyString(), anyString())
                .thenReturn(manager);
    } catch (Exception e) {
        e.printStackTrace();
    }
    FindAuthorityDescriptionRequestImpl validFindAuthorityDescription = mock(FindAuthorityDescriptionRequestImpl.class);
    PowerMockito.when(manager.createFindAuthorityDescriptionRequest(anyString(), anyString())).thenCallRealMethod();
    PowerMockito.when(manager.createFindAuthorityDescriptionRequest(Matchers.eq(VALID_IK),
            Matchers.eq(VALID_CATEGORY_NAME))).thenReturn(validFindAuthorityDescription);
    PowerMockito.when(manager.processRequest(Matchers.any(FindAuthorityDescriptionRequest.class)))
            .thenThrow(ManagerException.class);
    PowerMockito.when(manager.processRequest(Matchers.eq(validFindAuthorityDescription)))
            .thenReturn(generateValidAuthorityDescriptionResponse());
1

There are 1 answers

0
colourCoder On

The following code is a working example based on your mock setup (I've added dummy classes to make it runnable).

The code also contains asserts to verify that the mocked methods return expected values. Also, the real method createFindAuthorityDescriptionRequest is only called once.


Note: This was tested with `powermock 2.0.7` and `mockito 2.21.0`.

If issues persist, I'd suggest checking if the real method is not additionally called from somewhere else in your program (other than the code quoted in your problem statement).

package com.example.stack;

import org.junit.Test;
import org.junit.function.ThrowingRunnable;
import org.junit.runner.RunWith;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThrows;
import static org.mockito.ArgumentMatchers.*;
import static org.powermock.api.mockito.PowerMockito.mock;

@RunWith(PowerMockRunner.class)
@PrepareForTest(fullyQualifiedNames = "com.example.stack.*")
public class StackApplicationTests {

    private static final String VALID_IK = "IK";
    private static final String VALID_CATEGORY_NAME = "CATEGORY_NAME";
    private static final Object VALID_RESPONSE = "RESPONSE";

    @Test
    public void test() {
        Manager manager = mock(Manager.class);
        try {
            PowerMockito.whenNew(Manager.class).withArguments(anyString(), anyString())
                    .thenReturn(manager);
        } catch (Exception e) {
            e.printStackTrace();
        }

        FindAuthorityDescriptionRequestImpl validFindAuthorityDescription = mock(FindAuthorityDescriptionRequestImpl.class);

        PowerMockito.when(manager.createFindAuthorityDescriptionRequest(anyString(), anyString())).thenCallRealMethod();
        PowerMockito.when(manager.createFindAuthorityDescriptionRequest(eq(VALID_IK), eq(VALID_CATEGORY_NAME)))
                .thenReturn(validFindAuthorityDescription);
        PowerMockito.when(manager.processRequest(any(FindAuthorityDescriptionRequest.class)))
                .thenThrow(ManagerException.class);
        PowerMockito.when(manager.processRequest(eq(validFindAuthorityDescription)))
                .thenReturn(VALID_RESPONSE);


        // verify that the mock returns expected results
        assertEquals(Manager.REAL_RESULT, manager.createFindAuthorityDescriptionRequest("any", "any"));
        assertEquals(validFindAuthorityDescription, manager.createFindAuthorityDescriptionRequest("IK", "CATEGORY_NAME"));

        assertThrows(ManagerException.class, new ThrowingRunnable(){
            @Override
            public void run( ) {
                manager.processRequest(new FindAuthorityDescriptionRequestImpl());
            }
        });

        assertEquals(VALID_RESPONSE, manager.processRequest(validFindAuthorityDescription));

    }

}

interface FindAuthorityDescriptionRequest {}
class FindAuthorityDescriptionRequestImpl implements FindAuthorityDescriptionRequest {}
class ManagerException extends RuntimeException {}

class Manager {
    
    public static FindAuthorityDescriptionRequestImpl REAL_RESULT = new FindAuthorityDescriptionRequestImpl();
    public Manager(String s1, String s2) {}

    public FindAuthorityDescriptionRequest createFindAuthorityDescriptionRequest(String ik, String category) {
        return REAL_RESULT;
    }

    public Object processRequest(FindAuthorityDescriptionRequest request) {
        return null;
    }
}