问题
I am trying to replace JMock with Mockito (1.10.17). I have already done some unit tests successfully, but now I want to use the timeout feature
verify(publisher, timeout(5000)).notifySubscribers(any(BecameMasterMessage.class));
and I get this exception:
java.lang.VerifyError: (class: org/mockito/internal/verification/VerificationOverTimeImpl, method: verify signature: (Lorg/mockito/internal/verification/api/VerificationData;)V) Incompatible argument to function
at org.mockito.verification.Timeout.<init>(Timeout.java:32)
at org.mockito.verification.Timeout.<init>(Timeout.java:25)
at org.mockito.Mockito.timeout(Mockito.java:2164)
The issue happens in IntelliJ and with Maven. There is only 1 version of Mockito on the classpath. There is also JMock 2.5.1 on the classpath which I cannot remove since 99% of my unit tests still use JMock at this moment. I don't know if that has anything to do with it.
UPDATE: I tried with JMock 2.6.0 and Hamcrest 1.3 but the result is the same.
UPDATE 2:
This works:
Thread.sleep( 5000 );
verify( m_publisher ).notifySubscribers( any( BecameMasterMessage.class ) );
And this does not:
verify(publisher, timeout(5000)).notifySubscribers(any(BecameMasterMessage.class));
UPDATE 3: I have made a small test project that has the exact same problem: See https://github.com/wimdeblauwe/mockito-verify-problem and run it from IntelliJ or with Maven.
回答1:
The problem here is an unfortunate constellation between TestNG, JUnit and Mockto. To fix your issue, you just need to add a dependency to JUnit 4.0 or greater (the most recent version is currently 4.12):
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
Here are the details:
TestNG, which is apparently your testing framework, declares a dependency to the quite old JUnit version 3.8.1. Mockito does not declare a dependency to JUnit at all but it uses some JUnit classes that were introduced in JUnit 4.0 (!).
Edit:
The method Mockito#timeout()
in your example creates a Timeout
instance which in turn creates an instance of VerificationOverTimeImpl
. The method VerificationOverTimeImpl#verify()
handles an error of type ArgumentsAreDifferent
which is a subclass of org.junit.ComparisonFailure
.
From JUnit version 3.8.1 to 4.x the class hierarchy of ComparisonFailure
changed to having AssertionError
instead of Error
as base class. The VerifiyError
is caused because VerificationOverTimeImpl#handleVerifyException()
requires an AssertionError
but would be invoked with an Error
when JUnit 3.8.1 is used.
回答2:
EDIT: It seems stefan answered first. His diagnostic is almost correct, however, org.mockito.exceptions.verification.junit.ArgumentsAreDifferent
do extends junit.framework.ComparisonFailure
, that is present in JUnit 3.x and it is a dependency of TestNG 5.x.
The VerifyError
itself has probably something to do when the JVM is performing the linking as there is changes in the ComparisonFailure
type itself between JUnit 3.x and JUnit 4.x.
Anyway the issue in Mockito is that it uses a JUnit class where it shouldn't. And that Mockito don't support anymore JUnit 3.x.
tl;tr
We have an issue in the code internally the verification mode you are using use a JUnit class, that is not on the classpath. Adding JUnit in the dependency of your POM will fix things.
Thanks for reporting. I've created an issue on GitHub (#152)
long story
For some reason TestNG 5.xxx make the JVM fail with a VerifyError
, on a method that is not even called at that point.
java.lang.VerifyError: (class: org/mockito/internal/verification/VerificationOverTimeImpl, method: verify signature:
(Lorg/mockito/internal/verification/api/VerificationData;)V) Incompatible argument to function
But switching to the latest version of TestNG, 6.8.something make the JVM fail with an understandable cause : NoClassDefFoundError
java.lang.NoClassDefFoundError: junit/framework/ComparisonFailure
Which points to the real issue here, now there's only to find which class depends on JUnit. This class is ArgumentsAreDifferent
which extends junit.framework.ComparisonFailure
, this exception appears in a try/catch block in VerificationOverTimeImpl
that is needed for the timeout verification.
This issue has been there probably since 1.10.x when fixing some timeout issues.
Note I copied this answer on the mailing list as well.
来源:https://stackoverflow.com/questions/27721621/java-lang-verifyerror-with-mockito-1-10-17