Issue 212 in mockito: When parent class of the mock is not public then mock misbehaves

89 views
Skip to first unread message

moc...@googlecode.com

unread,
Aug 17, 2010, 3:39:30 PM8/17/10
to mocki...@googlegroups.com
Status: Accepted
Owner: szczepiq
Labels: Type-Defect Priority-Medium

New issue 212 by szczepiq: When parent class of the mock is not public then
mock misbehaves
http://code.google.com/p/mockito/issues/detail?id=212

When parent class of the mock is not public then mock misbehaves

moc...@googlecode.com

unread,
Aug 17, 2010, 3:43:59 PM8/17/10
to mocki...@googlegroups.com
Updates:
Labels: -Priority-Medium Priority-Low

Comment #1 on issue 212 by szczepiq: When parent class of the mock is not

Reported at the mailing list. See test ParentClassNotPublicVeryWeirdBugTest
for code sample. Remove @Ignore & run tests via ant to reproduce it.

The problem can be fixed very easily by making the parent class of the mock
public. Also this problem should be quite rare.

Fixing it requires digging into cglib and figuring out why the methods are
not intercepted in this scenario.

Patch from the community would be very welcome :)

moc...@googlecode.com

unread,
Oct 31, 2010, 4:19:05 PM10/31/10
to mocki...@googlegroups.com
Updates:
Status: New
Owner: ---

Comment #2 on issue 212 by szczepiq: When parent class of the mock is not

(No comment was entered for this change.)

moc...@googlecode.com

unread,
Jan 1, 2011, 7:24:46 AM1/1/11
to mocki...@googlegroups.com

Comment #3 on issue 212 by fob...@home.se: When parent class of the mock is

I recently had this problem, and I got stuck on it for quite a bit, since
the error message wasn't very clear.

I got a message like this:

org.mockito.exceptions.misusing.InvalidUseOfMatchersException:
Invalid use of argument matchers!
0 matchers expected, 4 recorded.
This exception may occur if matchers are combined with raw values:
//incorrect:
someMethod(anyObject(), "raw String");
When using matchers, all arguments have to be provided by matchers.
For example:
//correct:
someMethod(anyObject(), eq("String by matcher"));

For more info see javadoc for Matchers class.
at
com.googlecode.afdbaccess.cache.TransactionBase.executeQuery(TransactionBase.java:55)
at
com.googlecode.afdbaccess.cache.TransactionNoCommit.executeQuery(TransactionNoCommit.java:1)
at
com.googlecode.afdbaccess.web.common.login.UserInfoFetcherTest.mockTransaction(UserInfoFetcherTest.java:93)
at
com.googlecode.afdbaccess.web.common.login.UserInfoFetcherTest.testUserNotFound(UserInfoFetcherTest.java:40)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at
org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
at
org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at
org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
at
org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
at
org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:76)
at
org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
at
org.mockito.internal.runners.JUnit45AndHigherRunnerImpl.run(JUnit45AndHigherRunnerImpl.java:37)
at org.mockito.runners.MockitoJUnitRunner.run(MockitoJUnitRunner.java:62)
at
org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:49)
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)

It took some experiments to figure out that it started working if I made
the base class public instead of default/package-private. :)

If this defect can't be fixed easily, can the error message be made more
clear?

I made a smaller Eclipse project to try to recreate the problem, but in
that smaller case, I instead get this error message:

org.mockito.exceptions.misusing.InvalidUseOfMatchersException:
Misplaced argument matcher detected here:
-> at
nonpublicsuperclass.SubClassTest.testTheInheritedMethodThroughSubClassWithMatchers(SubClassTest.java:32)

You cannot use argument matchers outside of verification or stubbing.
Examples of correct usage of argument matchers:
when(mock.get(anyInt())).thenReturn(null);
doThrow(new RuntimeException()).when(mock).someVoidMethod(anyObject());
verify(mock).someMethod(contains("foo"))

Also, this error might show up because you use argument matchers with
methods that cannot be mocked.
Following methods *cannot* be stubbed/verified:
final/private/equals()/hashCode().

at
nonpublicsuperclass.SubClassTest.testTheInheritedMethodThroughSubClassWithMatchers(SubClassTest.java:32)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at
org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
at
org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at
org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
at
org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
at
org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:76)
at
org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
at
org.mockito.internal.runners.JUnit45AndHigherRunnerImpl.run(JUnit45AndHigherRunnerImpl.java:37)
at org.mockito.runners.MockitoJUnitRunner.run(MockitoJUnitRunner.java:62)
at
org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:49)
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)

When I don't use matchers, I get:

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:
1. you stub either of: final/private/equals()/hashCode() methods.
Those methods *cannot* be stubbed/verified.
2. inside when() you don't call method on mock but on some other object.
at
nonpublicsuperclass.SubClassTest.testTheInheritedMethodThroughSubClass(SubClassTest.java:27)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at
org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
at
org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at
org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
at
org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
at
org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:76)
at
org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
at
org.mockito.internal.runners.JUnit45AndHigherRunnerImpl.run(JUnit45AndHigherRunnerImpl.java:37)
at org.mockito.runners.MockitoJUnitRunner.run(MockitoJUnitRunner.java:62)
at
org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:49)
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)

I've attached the Eclipse project I used to get the later two stack traces.
The first stacktrace I'm only able to get with my full code.


Attachments:
Mockito-inheritedmethodfail.zip 1.2 MB

moc...@googlecode.com

unread,
Jan 2, 2011, 7:42:30 AM1/2/11
to mocki...@googlegroups.com

Comment #4 on issue 212 by szczepiq: When parent class of the mock is not

Very nice detailed report ;) THANKS!

Since mocking classes that are not public does not work I guess we should
make it fail fast at mock creation time.

moc...@googlecode.com

unread,
Jan 2, 2011, 4:31:29 PM1/2/11
to mocki...@googlegroups.com
Updates:
Owner: szczepiq

Comment #5 on issue 212 by szczepiq: When parent class of the mock is not

This problem is related to bridge methods...

moc...@googlecode.com

unread,
Apr 28, 2011, 11:42:43 AM4/28/11
to mocki...@googlegroups.com

Comment #6 on issue 212 by brice.du...@gmail.com: When parent class of the
mock is not public then mock misbehaves
http://code.google.com/p/mockito/issues/detail?id=212

Issue 258 has been merged into this issue.

moc...@googlecode.com

unread,
May 11, 2011, 4:26:56 AM5/11/11
to mocki...@googlegroups.com

Comment #7 on issue 212 by szcze...@gmail.com: When parent class of the
mock is not public then mock misbehaves
http://code.google.com/p/mockito/issues/detail?id=212

Unfortunately, it seems that there is a bug in java. I filed the report
here: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7011164

moc...@googlecode.com

unread,
Oct 7, 2011, 4:50:08 AM10/7/11
to mocki...@googlegroups.com

Comment #8 on issue 212 by brice.du...@gmail.com: When parent class of the
mock is not public then mock misbehaves
http://code.google.com/p/mockito/issues/detail?id=212

Issue 274 has been merged into this issue.

moc...@googlecode.com

unread,
Oct 8, 2011, 7:28:53 PM10/8/11
to mocki...@googlegroups.com

Comment #9 on issue 212 by sharedo...@gmail.com: When parent class of the
mock is not public then mock misbehaves
http://code.google.com/p/mockito/issues/detail?id=212

Another example: we just ran into this trying to test SSHClient setup in
the nice sshj [1] library (great alternative to JSch!). SSHClient [2] (the
main entry point) inherits from SocketClient [3] which, unfortunately from
the point of view of this bug, is package visible.

The connect() family of methods thus cannot be stubbed out in a test,
meaning that writing unit tests without *actual* hosts to connect to is
hard :-(

[1] https://github.com/shikhar/sshj
[2]
https://github.com/shikhar/sshj/blob/master/src/main/java/net/schmizz/sshj/SSHClient.java
[3]
https://github.com/shikhar/sshj/blob/master/src/main/java/net/schmizz/sshj/SocketClient.java

moc...@googlecode.com

unread,
Oct 9, 2011, 7:38:30 AM10/9/11
to mocki...@googlegroups.com

Comment #10 on issue 212 by sharedo...@gmail.com: When parent class of the
mock is not public then mock misbehaves
http://code.google.com/p/mockito/issues/detail?id=212

The workaround we use in our case: define a subclass of the class to test
that adds delegate methods for those methods we need to stub. E.g.

public class MockitoFriendlySSHClient extends SSHClient {
// we need to stub this
@Override
public void connect(String hostname, int port) throws IOException {
super.connect(hostname, port);
}
}

and in the test

SSHClient client = mock(MockitoFriendlySSHClient.class);

Of course, this is a little maintenance-intensive if the base class
changes, but it's at least compile-safe.

moc...@googlecode.com

unread,
Feb 6, 2012, 3:22:38 PM2/6/12
to mocki...@googlegroups.com

Comment #11 on issue 212 by ba...@acar.org.uk: When parent class of the
mock is not public then mock misbehaves
http://code.google.com/p/mockito/issues/detail?id=212

Given that the Java guys responded with an evaluation of "Not bug" - is
this something that can be worked around within Mockito, rather than inside
our test code?

moc...@googlecode.com

unread,
Feb 7, 2012, 6:33:32 AM2/7/12
to mocki...@googlegroups.com

Comment #12 on issue 212 by brice.du...@gmail.com: When parent class of the
mock is not public then mock misbehaves
http://code.google.com/p/mockito/issues/detail?id=212

Maybe maybe not, it might require tremendous effort, maybe solving this
case would break other legitimate cases. We are interested for some time to
experience with other bytecode engine, they might help to solve this case.
Speaking for myself, I would not bet on a fix of this bug the near future.

moc...@googlecode.com

unread,
Feb 8, 2012, 5:41:29 AM2/8/12
to mocki...@googlegroups.com

Comment #13 on issue 212 by szcze...@gmail.com: When parent class of the
mock is not public then mock misbehaves
http://code.google.com/p/mockito/issues/detail?id=212

@sharedocs1 - I gather that the workaround with making the parent public is
not possible in your scenario?

This problem cannot be completely fixed. With some minor changes to cglib
we might have a workaround for most cases, let's say 90%. That might be
good enough but I would need to pair with someone on that as it's kinda
tricky stuff and makes me uncomfortable doing it.

moc...@googlecode.com

unread,
Feb 8, 2012, 10:21:44 AM2/8/12
to mocki...@googlegroups.com

Comment #14 on issue 212 by sharedo...@gmail.com: When parent class of the
mock is not public then mock misbehaves
http://code.google.com/p/mockito/issues/detail?id=212

> I gather that the workaround with making the parent public is not
> possible in your scenario?

No, unfortunately not - the parent is part of a 3rd-party library. But
we're pretty happy with the workaround we found (which is essentially
creating a "new" public parent using a subclass that we *do* control).

moc...@googlecode.com

unread,
May 14, 2012, 6:45:56 PM5/14/12
to mocki...@googlegroups.com

Comment #15 on issue 212 by jgang...@gmail.com: When parent class of the
mock is not public then mock misbehaves
http://code.google.com/p/mockito/issues/detail?id=212

i just got bit by this myself - if there is no immediate fix available,
could at least the error message be improved?

moc...@googlecode.com

unread,
Jul 27, 2012, 4:07:43 PM7/27/12
to mocki...@googlegroups.com

Comment #16 on issue 212 by rogerpack2005: When parent class of the mock is
Fascinatingly (and a bit startling), I also got this exception message when
I attempted to run Mockito.when(an_easymock_object....) should I file a
separate bug for this?

moc...@googlecode.com

unread,
Aug 2, 2012, 8:59:33 AM8/2/12
to mocki...@googlegroups.com

Comment #17 on issue 212 by brice.du...@gmail.com: When parent class of the
mock is not public then mock misbehaves
http://code.google.com/p/mockito/issues/detail?id=212

@rogerpack which error message do you see, if you think you have the same
issue with same cause, it might not be necessary.

Cheers,
Brice

moc...@googlecode.com

unread,
Oct 9, 2012, 6:14:08 AM10/9/12
to mocki...@googlegroups.com

Comment #18 on issue 212 by Frank.Ja...@gmail.com: When parent class of the
mock is not public then mock misbehaves
http://code.google.com/p/mockito/issues/detail?id=212

We're experiencing the same issue with java 6 and subclassing a non-public
class which contains a public method.
Would the check for fast-fail not be feasible at
org.mockito.internal.util.MockUtil.createMock(Class<T>, MockSettingsImpl),
where we could check all methods of a class to be stubbed with the
following code

...
checkForUnmockablePublicMethods(classToMock);
...
private void checkForUnmockablePublicMethods(Class<?> clazz) {
Method[] methods = clazz.getMethods();
for (Method m : methods) {
if (m.isBridge() && Modifier.isPublic(m.getModifiers())) {
throw new IllegalStateException(String.format("Method %s.%s is
publicly visible but not mockable.", clazz.getCanonicalName(),
m.getName()));
}
}
}

moc...@googlecode.com

unread,
Oct 12, 2012, 3:02:22 AM10/12/12
to mocki...@googlegroups.com

Comment #19 on issue 212 by szcze...@gmail.com: When parent class of the
mock is not public then mock misbehaves
http://code.google.com/p/mockito/issues/detail?id=212

I'm not sure we should just fail fast when parent is non-public. The
problem only applies to methods that are declared on the parent. Mocking
the methods on the child class works fine. There might be users that have
working tests because they only mock the child class methods. When we
introduce fail fast switch their tests starts breaking.

This is a similar problem to final methods. A class has final methods but
the users may only be mocking the regular methods so we shouldn't fail fast
when a mocked class has some final method.

I realize that it's a pain to debug this problem. I'll try to allocate some
time to fix this in cglib sometime soon.

moc...@googlecode.com

unread,
Feb 4, 2013, 1:36:31 PM2/4/13
to mocki...@googlegroups.com

Comment #20 on issue 212 by brice.du...@gmail.com: When parent class of the
mock is not public then mock misbehaves
http://code.google.com/p/mockito/issues/detail?id=212

Issue 417 has been merged into this issue.

moc...@googlecode.com

unread,
Feb 4, 2013, 4:20:11 PM2/4/13
to mocki...@googlegroups.com

Comment #21 on issue 212 by omri.spe...@gmail.com: When parent class of the
mock is not public then mock misbehaves
http://code.google.com/p/mockito/issues/detail?id=212

Here is a solution that worked for me (also written in issue 417):
1- add PowerMockito to your project
2- Use PM runner
3- @PrepareForTest(TheProblematicClass.class) // solves the issue
4- @PowerMockIgnore({"javax.crypto.*" }) // custom class loading messes
with crypto
and use PowerMock.mock for TheProblematicClass.
All other mocking (annotations and all) work as usual.

moc...@googlecode.com

unread,
Feb 5, 2013, 4:37:31 AM2/5/13
to mocki...@googlegroups.com

Comment #22 on issue 212 by brice.du...@gmail.com: When parent class of the
mock is not public then mock misbehaves
http://code.google.com/p/mockito/issues/detail?id=212

moc...@googlecode.com

unread,
Jun 18, 2013, 4:27:05 PM6/18/13
to mocki...@googlegroups.com

Comment #23 on issue 212 by Visionar...@gmail.com: When parent class of the
mock is not public then mock misbehaves
http://code.google.com/p/mockito/issues/detail?id=212

I ran into the aame issue as #16 with an EasyMock class. The class that is
being mocked is package/default visibility, but not its "parent" (Object).
Recommend the exception message be appropriately updated.

--
You received this message because this project is configured to send all
issue notifications to this address.
You may adjust your notification preferences at:
https://code.google.com/hosting/settings

moc...@googlecode.com

unread,
Dec 4, 2013, 9:31:30 AM12/4/13
to mocki...@googlegroups.com

Comment #24 on issue 212 by brice.du...@gmail.com: When parent class of the
mock is not public then mock misbehaves
http://code.google.com/p/mockito/issues/detail?id=212

Issue 463 has been merged into this issue.

moc...@googlecode.com

unread,
Jan 9, 2014, 4:19:29 PM1/9/14
to mocki...@googlegroups.com

Comment #25 on issue 212 by albers...@gmail.com: When parent class of the
mock is not public then mock misbehaves
http://code.google.com/p/mockito/issues/detail?id=212

Probably solved by changes for #434

moc...@googlecode.com

unread,
Oct 15, 2014, 7:57:24 PM10/15/14
to mocki...@googlegroups.com

Comment #26 on issue 212 by phave...@gmail.com: When parent class of the
mock is not public then mock misbehaves
https://code.google.com/p/mockito/issues/detail?id=212

changes for issue #434 did not fix this issue (#212)

moc...@googlecode.com

unread,
Oct 19, 2014, 12:24:36 PM10/19/14
to mocki...@googlegroups.com

Comment #27 on issue 212 by brice.du...@gmail.com: When parent class of the
mock is not public then mock misbehaves
https://code.google.com/p/mockito/issues/detail?id=212

The PR has not been merged as it caused other problems

moc...@googlecode.com

unread,
Feb 15, 2015, 8:30:34 PM2/15/15
to mocki...@googlegroups.com
Updates:
Status: Fixed

Comment #28 on issue 212 by brice.du...@gmail.com: When parent class of the
mock is not public then mock misbehaves
https://code.google.com/p/mockito/issues/detail?id=212

Follow up of that issue on on google code is the Github issue 168 =>
https://github.com/mockito/mockito/pull/168, that means closing this issue
to keep the discussion there.

It appears that he proxies generated by CGLIB (with the version we use) are
the cause of this bug, ByteBuddy proxies are not affected. The mock engine
is being change for mockito 2.x =>
https://github.com/mockito/mockito/pull/171
Reply all
Reply to author
Forward
0 new messages