blindsnowmobile
blindsnowmobile

Reputation: 4328

Mock final method in inner class with PowerMockito

I'm having trouble stubbing a final method, which is used inside of a class I'm trying to test. The problematic line in my test class is here:

PowerMockito.when(connectionMock.authUser("fake-user", "fake-password")).thenReturn("random string");

which throws a NullPointerException. My test class looks like this:

@RunWith(PowerMockRunner.class)
@PrepareForTest({MyClass.class, APIClientConnection.class})
public class MyClassTest {
    @Test
    public void apiConnect() throws Exception {
        MyClass c = new MyClass();
        APIClientConnection connectionMock = PowerMockito.mock(APIClientConnection.class);
        PowerMockito.whenNew(APIClientConnection.class).withAnyArguments().thenReturn(connectionMock);
        PowerMockito.when(connectionMock.authUser("fake-user", "fake-password")).thenReturn("random string");
        c.apiConnect("fake-host", 80, "fake-user", "fake-password");
    }
}

The class I'm testing is as follows:

public class MyClass {
    public MyClass() { }
    public APIClientConnection apiConnect(String host, int port, String user, String pass) {
            conn = new APIClientConnection(host, port);
            conn.authUser(user, pass);
    }
}

Where authUser() is defined final like so:

public class APIClientConnection {
    public final String authUser(String username, String password) {
        ...
    }
}

I'm following along with How to mock non static methods using PowerMock and Can Powermockito mock final method in non-final concrete class?. I've tried some variations such as using Mockito instead of PowerMock to stub authUser, and adding APIClientConnection.class to the PrepareForTest annotation. I can't figure out why it isn't working though. What am I doing wrong?

Upvotes: 0

Views: 1581

Answers (2)

blindsnowmobile
blindsnowmobile

Reputation: 4328

Operator error :X

I had two typos due to my sanitizing the code before posting. In the error pointed out by the user above, the parameters in the stub, and the parameters passed to the actual method call did not match. This wasn't causing my issue because the typo was introduced when I typed it into the post, and wasn't reflected in the code I was running.

The second typo was actually causing my issue. My actual code was using:

APIClientConnection conn = Mockito.mock(APIClientConnection.class);

Which I somehow managed to turn into this in my post:

APIClientConnection conn = PowerMockito.mock(APIClientConnection.class);

Once I switched "Mockito.mock" to "PowerMockito.mock" in my code, it started working. So somehow I managed to introduce the fix while posting my own question. :/

Sincere apologies to anyone who has been staring at this wondering what was going on! I've been staring at it for too long I guess. The code above should work, maybe it will be helpful to someone.

Upvotes: 1

Juan Cruz Soler
Juan Cruz Soler

Reputation: 8254

Your problem is here

PowerMockito.when(connectionMock.authUser("user", "password")).thenReturn("random string");
c.apiConnect("fake-host", 80, "fake-user", "fake-password");

You are indicating that the method should be stubbed when a user logs with credentials user/password, but you are sending fake-user/fake-password.

Replace the last line with c.apiConnect("fake-host", 80, "user", "password");

Upvotes: 2

Related Questions