jmockit / jmockit1

Advanced Java library for integration testing, mocking, faking, and code coverage
Other
465 stars 240 forks source link

On some JDKs: Attempted to record invocation to mocked method from outside expectation block #69

Closed borisbrodski closed 10 years ago

borisbrodski commented 10 years ago

On some JDKs we are getting

java.lang.IllegalStateException: Attempted to record invocation to mocked method from outside expectation block:

exception using JMockit 1.11.

Tested so far:

In order to analyse the problem I set a breakpoint in the RecondPhase.getCallerClass() method and ran the following snippet from the display view.

for (int i = 0; i < 8; i++) {
  System.out.println("" + i + ": " + Reflection.getCallerClass(i));
}

It outputs on jdk1.7.0_25 (64bit)

0: class sun.reflect.Reflection
1: class sun.reflect.Reflection
2: class mockit.internal.expectations.RecordPhase
3: class mockit.internal.expectations.RecordPhase
4: class mockit.internal.expectations.RecordAndReplayExecution
5: class my.MockedClass
6: class my.TestClass$1
7: class org.eclipse.xtend.jmockit.JMockitExtension$6

and it outputs on jdk1.7.0_60 (64 bit)

0: class sun.reflect.Reflection
1: class mockit.internal.expectations.RecordPhase
2: class mockit.internal.expectations.RecordPhase
3: class mockit.internal.expectations.RecordAndReplayExecution
4: class my.MockedClass
5: class my.TestClass$1
6: class org.eclipse.xtend.jmockit.JMockitExtension$6
7: class org.eclipse.xtend.jmockit.JMockitExtension

Both Windows 7 64bit

rliesenfeld commented 10 years ago

I know, this is due to an incompatible change to an internal API (sun.reflect.Reflection) introduced by Oracle in early versions of JDK 1.7. That change was rolled back, because it caused failures in high-profile libraries such as groovy.

I think it's reasonable to leave its use in JMockit as is, if it works in the recent versions of the JDK. That's what the other projects are doing too, anyway (as far as I know).