How stub private methods (without running method)?

3,000 views
Skip to first unread message

simonr25

unread,
Oct 25, 2011, 9:25:58 AM10/25/11
to PowerMock

Hello (+ thank you for your previous quick responses).

Is it possible to stub a private method such that the private method
is not called and the stub returns a value in place of that normally
returned by the private method.

I/we am using powermock and mockito.

I require to test 'methodToTest()' below, which calls private
'getNewStr()'. I need to stub 'getNewStr()' so that it is not called
and a mock object (in this case a String "hi") is returned. The
procedure I've been trying is as follows (although the correct value
is returned, getNewStr is also run):

public class StatProduct {
public String methodToTest() {
return getNewStr();
}
private String getNewStr() {
return "hello";
}
}

@RunWith(PowerMockRunner.class)
@PrepareForTest(StatProduct.class)
public class TestPowProduct {
@Test
public void goOnThen() throws Exception{
StatProduct underTest = spy(new StatProduct());
when(underTest, "getNewStr").thenReturn("hi");
assertEquals("hi",underTest.methodToTest());
verifyPrivate(underTest).invoke("getNewDate");
}
}

n.b. for comparison:
If getNewStr() was not private I could use:
doReturn("hi").when(underTest).getNewStr();
and if using a mock object I could use:
when(mock.getNewStr()).thenReturn("hi");
Both of these would return the String object without
running the getNewStr() method.

Kind regards,
Simon

Brice Dutheil

unread,
Oct 25, 2011, 9:58:14 AM10/25/11
to powe...@googlegroups.com
Try

when(underTest, "getNewStr").withNoArguments().thenReturn("hi");

Hope that helps :)

-- 
Brice



--
You received this message because you are subscribed to the Google Groups "PowerMock" group.
To post to this group, send email to powe...@googlegroups.com.
To unsubscribe from this group, send email to powermock+...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/powermock?hl=en.


simonr25

unread,
Oct 25, 2011, 11:12:58 AM10/25/11
to PowerMock
Thank you Brice.

Please could you tell me which package contains withNoArguments - i.e.
what I require to import?

[javac] c:\Project\...\TestStatProduct.java:81: cannot find symbol
[javac] symbol : method withNoArguments()
[javac] c:\Project\...\TestStatProduct.java:81: cannot find symbol
[javac] location: interface
org.mockito.stubbing.OngoingStubbing<java.lang.Object>
[javac] when(underTest,
"getNewStr").withNoArguments().thenReturn("hi");
[javac] ^
[javac] 1 error

Thank you,
Simon

Brice Dutheil

unread,
Oct 25, 2011, 11:21:56 AM10/25/11
to powe...@googlegroups.com
You are using the wrong static 'when' :)
Check your static import for a Mockito.when, and replace it. Or in the test use the following

PowerMockito.when(underTest, "getNewStr").withNoArguments().thenReturn("hi");

-- 
Brice

simonr25

unread,
Oct 25, 2011, 12:29:25 PM10/25/11
to PowerMock



Hi Brice,see below:

import org.junit.Test;
import org.junit.runner.RunWith;
import static org.junit.Assert.*;
import java.util.Date;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import static org.powermock.api.mockito.PowerMockito.mock;
import org.powermock.modules.junit4.rule.*;
import static org.powermock.api.mockito.PowerMockito.when;
import static org.powermock.api.mockito.PowerMockito.doReturn;
import static org.powermock.api.mockito.PowerMockito.spy;
import static org.powermock.api.mockito.PowerMockito.verifyPrivate;

@RunWith(PowerMockRunner.class)
@PrepareForTest(StatProduct.class)
public class TestStatProduct {
@Test
public void goOnThen() throws Exception{
StatProduct underTest = spy(new StatProduct());
PowerMockito.when(underTest,
"getNewStr").withNoArguments().thenReturn("hi");
assertEquals("hi",underTest.methodToTest());
verifyPrivate(underTest).invoke("getNewStr");
}
}

[javac] c:\Project\...\TestStatProduct.java:82: cannot find symbol
[javac] symbol : method withNoArguments()
[javac] location: interface
org.mockito.stubbing.OngoingStubbing<java.lang.Object>
[javac] PowerMockito.when(underTest,
"getNewStr").withNoArguments().thenReturn("hi");
[javac] ^
[javac] 1 error

I also tried importing:
org.powermock.api.mockito.expectation.WithoutExpectedArguments.*;
same error.

am using: powermock 1.4.10

Kind regards,
Simon

Brice Dutheil

unread,
Oct 25, 2011, 12:47:36 PM10/25/11
to powe...@googlegroups.com
Oh damn, I got you the wrong 'when' too.


This code should work :
import org.junit.Test;
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.powermock.api.mockito.PowerMockito.spy;
import static org.powermock.api.mockito.PowerMockito.verifyPrivate;
import static org.powermock.api.mockito.PowerMockito.when;

@RunWith(PowerMockRunner.class)
@PrepareForTest(StatProduct.class)
public class SomeTest {


    @Test
    public void goOnThen() throws Exception{
        StatProduct underTest = spy(new StatProduct());

        PowerMockito.when(underTest, "getNewStr").thenReturn("hi");
        assertEquals("hi",underTest.methodToTest());
        verifyPrivate(underTest).invoke("getNewStr");
    }
}



And the star here

public class StatProduct {
    private String getNewStr() { return "bob"; }

    public String methodToTest() { return getNewStr(); }
}

-- 
Brice

simonr25

unread,
Oct 25, 2011, 1:21:04 PM10/25/11
to PowerMock
Hi Brice,
Thank you for your reply.
I found when using the latest change that when the following command
is carried out,
the private getNewStr() method is run once:
PowerMockito.when(underTest, "getNewStr").thenReturn("hi");

I require that the private method is never run.

If the getNewStr() method has an error (e.g. throws a runtimeexception
- which it
just so happens the private method I require to mock does) then the
test fails at this
point, the assertEquals(...) line onwards do not get run.
If the getNewStr() line does not throw an exception, then the rest
works fine.

kind regards,
Simon

Brice Dutheil

unread,
Oct 25, 2011, 1:27:35 PM10/25/11
to powe...@googlegroups.com
If you that your private method is never called, then write this

PowerMockito.verifyPrivate(underTest, Mockito.never()).invoke("getNewStr");




-- 
Brice

simonr25

unread,
Oct 25, 2011, 1:53:13 PM10/25/11
to PowerMock
Thank you Brice.

I can not avoid the private method getNewStr() being called from
methodToTest() -
infact this is part of the test - that the private method is invoked.
However it is required that the body of the private method not be run.
i.e. the
private method needs to effectively be mocked/stubbed and return an
alternative
object/string, i.e. "hi" in the example.

The command PowerMockito.when(underTest,
"getNewStr").thenReturn("hi");
seems to (infact does) run the body of the private method - which is
not what is
required - plus not what I would expect.

Thank you again.
Simon

Johan Haleby

unread,
Oct 25, 2011, 4:28:22 PM10/25/11
to powe...@googlegroups.com
Hi,

If I understand you correctly you I think the simplest thing would be to use the stubbing API:

stub(method(StatProduct.class, "getNewStr")).toReturn("hi");

You can find the "stub" and "method" methods in org.powermock.api.support.membermodification.MemberModifier and org.powermock.api.support.membermodification.MemberMatcher. You also need to prepare the StatProduct class for test.

/Johan

simonr25

unread,
Oct 27, 2011, 3:30:56 AM10/27/11
to PowerMock
Hi,
This resolves the issue.
Thank you,
Simon
> ...
>
> read more »

RealObject

unread,
Jul 22, 2013, 7:36:12 PM7/22/13
to powe...@googlegroups.com
Hi,

I got the same problem, except that I want to it return different values on different calls. But here are only unchainable toReturn() and toThrow(), no toAnswer(Answer) like the when() method does.

How to work around? (PowerMock 1.5.1)


(It would be great if this can work with the standard doReturn().when() pattern.)

Thanks

Johan Haleby

unread,
Jul 25, 2013, 4:05:40 AM7/25/13
to powe...@googlegroups.com
In these cases you would have to replace the method if an InvocationHandler, e.g. 

replace(method(X.class, "y")).with(new InvocationHandler() {
            public Object invoke(Object object, Method method, Object[] args) throws Throwable {
                if(args[0].equals(..)) {
                     return ..;
                }
                return ..;
            }
        })

Regards,
/Johan


To unsubscribe from this group and stop receiving emails from it, send an email to powermock+...@googlegroups.com.

To post to this group, send email to powe...@googlegroups.com.
Visit this group at http://groups.google.com/group/powermock.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Reply all
Reply to author
Forward
0 new messages