Question

I have written a unit test using JMock 2.6.0-RC2 that makes use of several package private classes. For some reason, this causes an IllegalAccessError:

java.lang.IllegalAccessError: tried to access class foo.PackagePrivateClass from class $Proxy6
    at $Proxy6.getInstance(Unknown Source)
    at foo.UsingClass.<init>(UsingClass.java:6)
    at foo.FailingTest.testFailure(FailingTest.java:29)

I have uploaded a minimal Maven project that demonstrates the issue to here: http://dl.dropbox.com/u/108474287/example-project.zip. The relevant code is also shown below (it's fairly concise).

Why am I seeing an error in my test? The test class is part of the same package as the tested classes, so I would not expect access control to be an issue.

Some interesting observations:

  1. If I change ExampleInterface to be package private (rather than public), the problem goes away. Sadly, in my real-life project this is not a possibility.

  2. The exception only occurs if I return a value from my mock object. Those who download my example project will see another test in which null is returned; this test passes.

  3. If I move the all the classes into the default package, the tests pass! If all the classes remain in package foo, the tests fail.

Below are the files contained in my project. The ZIP I linked to above is a small Maven project that houses all of these.

I have also posted this question to the JMock developer list. I will update this question if I receives answers there (and vice versa).


FailingTest.java

package foo;

// Imports omitted

@RunWith(JMock.class)
public class FailingTest {

  private static final PackagePrivateClass EXAMPLE_INSTANCE = 
      new PackagePrivateClass();

  public Mockery context = new JUnit4Mockery();

  @Test
  public void testFailure() {
    final ExampleInterface exampleInterface = context
        .mock(ExampleInterface.class);

    context.checking(new Expectations() {
      {
        oneOf(exampleInterface).getInstance(); 
        will(returnValue(EXAMPLE_INSTANCE));
      }
    });

    new UsingClass(exampleInterface); <-- exception thrown from constructor
  }
}

ExampleInterface.java

package foo;

public interface ExampleInterface {
  PackagePrivateClass getInstance();
}

PackagePrivateClass.java

package foo;

class PackagePrivateClass {

  PackagePrivateClass() {}

  @Override
  public String toString() {
    return "Hello, World!";
  }
}

UsingClass.java

package foo;

class UsingClass {

  UsingClass(ExampleInterface exampleInterface) {
    PackagePrivateClass bar = exampleInterface.getInstance(); // <--- exception
    System.out.println(bar);                                  // originates here
  }
}
Was it helpful?

Solution

To provide an update for future readers....

Currently, I believe this is a bug in JMock. I've filed it on the JMock github page: https://github.com/jmock-developers/jmock-library/issues/43. No responses yet (nor to my comment on the mailing list).

I've since switched to Mockito, which is able to handle exactly the same situation without error.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top