How to mock non static methods in a final class with static getInstance method

3,905 views
Skip to first unread message

GeoffH

unread,
Jan 7, 2010, 9:11:50 AM1/7/10
to PowerMock
I have a legacy class with

a) a private static instance
b) a private constructor
c) a public static getInstance() method
d) a number of non static methods

I am having trouble stubbing any of the non static methods
I am using PowerMock 1.3.5-full with Mockito 1.8.2

The class (reduced to a minimal representation) looks something like:

public final class MyFinalClass
{
private static MyFinalClass singleInstance;

private MyFinalClass(){
// do nothing
}

public static MyFinalClass getInstance(){
if (MyFinalClass.singleInstance == null)
{
singleInstance = new MyFinalClass();
}
return singleInstance;
}

public String nonStaticGetString(){
return "RealReturn";
}
}


I've set up a mock with the following statements:

MyFinalClass mockClass;
PowerMockito.mock(MyFinalClass.class);
PowerMockito.when(MyFinalClass.getInstance()).thenCallRealMethod();
mockClass = MyFinalClass.getInstance();

PowerMockito.when(mockClass.nonStaticGetString(key)).thenReturn
("MockedReturn");

I can run a test that shows that mockClass is as expected
When I add the 'PowerMockito.when' statement, I get the following
exception

org.mockito.exceptions.misusing.MissingMethodInvocationException:
when() requires an argument which has to be a method call on a mock.
For example:
when(mock.getArticles()).thenReturn(articles);
Also, this error might show up because you stub final/private/equals()
or hashCode() method.
Those methods *cannot* be stubbed/verified.

at org.powermock.api.mockito.PowerMockito.when(PowerMockito.java:343)

I tried PowerMockito.mockStatic in place of PowerMockito.mock with
similar results

The article at
http://code.google.com/p/powermock/wiki/MockitoUsage13
refers to a spyStatic method for mocking a specific method
- but I could not access it

The article at
http://code.google.com/p/powermock/wiki/MockitoUsage
refers to mockStaticPartial for mocking a specific method
- but I could not access it

Any suggestions or help with what is wrong or how to mock the non
static methods would be much appreciated

Thanks

GeoffH

GeoffH

unread,
Jan 7, 2010, 10:52:01 AM1/7/10
to PowerMock
I made some progress by using the following statements:
MyFinalClass mockClass = PowerMockito.spy(MyFinalCLass.getInstance());
PowerMockito.when(mockClass, "nonStaticGetString", key).thenReturn
(value);
- and ran a test to check that
a) mockClass was created correctly
b) the method "nonStaticGetString" returned the correct value

I then used mockClass in another legacy class through its setter:
public void setparameterManager(MyFinalCLass parameterManager){
this.parameterManager = parameterManager;
}

- and attempted to test a method in the second legacy class
this test invokes the statement:
return this.parameterManager.nonStaticGetString(key);

In Eclipse, I got the following trace in the Console:

java.lang.RuntimeException: test should never throw an exception to
this level
at
org.junit.internal.runners.MethodRoadie.runBeforesThenTestThenAfters
(MethodRoadie.java:97)
at
org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl
$PowerMockJUnit44MethodRunner.executeTest
(PowerMockJUnit44RunnerDelegateImpl.java:309)
at
org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl
$PowerMockJUnit44MethodRunner.runBeforesThenTestThenAfters
(PowerMockJUnit44RunnerDelegateImpl.java:297)
at org.junit.internal.runners.MethodRoadie.runTest(MethodRoadie.java:
84)
at org.junit.internal.runners.MethodRoadie.run(MethodRoadie.java:49)
at
org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.invokeTestMethod
(PowerMockJUnit44RunnerDelegateImpl.java:222)
at
org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.runMethods
(PowerMockJUnit44RunnerDelegateImpl.java:161)
at
org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl
$1.run(PowerMockJUnit44RunnerDelegateImpl.java:135)
at org.junit.internal.runners.ClassRoadie.runUnprotected
(ClassRoadie.java:34)
at org.junit.internal.runners.ClassRoadie.runProtected
(ClassRoadie.java:44)
at
org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.run
(PowerMockJUnit44RunnerDelegateImpl.java:133)
at
org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.run
(JUnit4TestSuiteChunkerImpl.java:112)
at
org.powermock.modules.junit4.common.internal.impl.AbstractCommonPowerMockRunner.run
(AbstractCommonPowerMockRunner.java:55)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run
(JUnit4TestReference.java:46)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run
(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests
(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests
(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run
(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main
(RemoteTestRunner.java:197)

Any help or suggestions gratefully received

Thanks

GeoffH

> The article athttp://code.google.com/p/powermock/wiki/MockitoUsage13


> refers to a spyStatic method for mocking a specific method
>  - but I could not access it
>

> The article athttp://code.google.com/p/powermock/wiki/MockitoUsage

GeoffH

unread,
Jan 8, 2010, 3:55:13 AM1/8/10
to PowerMock
I ran the same tests from a Windows command prompt using the command

mvn clean test

The tests completed successfully, so an Eclipse related problem

Anyone seen anything like this and have a solution

Thanks

GeoffH

Johan Haleby

unread,
Jan 8, 2010, 4:26:51 AM1/8/10
to powe...@googlegroups.com
Hi,

I've got the exception you're referring to a couple of times when I'm developing PowerMock but just as it says it should never happen (it's usually a bug). The problem is that JUnit swallows the causing exeception so it's really difficult to see what's actually causing the error. You could put a break-point at the place where JUnit throws the exception and see what the real cause of the problem is. How ever if it works in maven then perhaps it's an Eclipse issue, have you tried a new workspace and/or tried cleaning?

/Johan

--
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.




GeoffH

unread,
Jan 8, 2010, 5:23:32 AM1/8/10
to PowerMock
Johan,

Thanks for the suggestion
I restarted Eclipse with the -clean option in eclipse.ini and the
problem has 'gone away'

Referring back to my second post, would the following construct

MyFinalClass mockClass = PowerMockito.spy(MyFinalCLass.getInstance());
PowerMockito.when(mockClass, "nonStaticGetString", key).thenReturn
(value);

be the recommended way to mock the type of (legacy) class I described:


a) a private static instance
b) a private constructor
c) a public static getInstance() method
d) a number of non static methods

Thanks

GeoffH

On Jan 8, 9:26 am, Johan Haleby <johan.hal...@gmail.com> wrote:
> Hi,
>
> I've got the exception you're referring to a couple of times when I'm
> developing PowerMock but just as it says it should never happen (it's
> usually a bug). The problem is that JUnit swallows the causing exeception so
> it's really difficult to see what's actually causing the error. You could
> put a break-point at the place where JUnit throws the exception and see what
> the real cause of the problem is. How ever if it works in maven then perhaps
> it's an Eclipse issue, have you tried a new workspace and/or tried cleaning?
>
> /Johan
>

> > powermock+...@googlegroups.com<powermock%2Bunsu...@googlegroups.com>

Reply all
Reply to author
Forward
0 new messages