在JMock中访问包私有类时出现IllegalAccessError

时间:2013-02-21 15:27:24

标签: java junit jmock

我使用JMock 2.6.0-RC2编写了一个单元测试,它使用了几个包私有类。出于某种原因,这会导致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)

我已经上传了一个最小的Maven项目,该项目向我们展示了这个问题:http://dl.dropbox.com/u/108474287/example-project.zip。相关代码也如下所示(它相当简洁)。

为什么我的测试中出现错误?测试类是与测试类相同的包的一部分,因此我不希望访问控制成为问题。

一些有趣的观察:

  1. 如果我将ExampleInterface更改为包私有(而非公开),则问题就会消失。可悲的是,在我的现实生活中,这不太可能。

  2. 只有从模拟对象返回值时才会发生异常。下载我的示例项目的人将看到另一个测试,其中返回null;这个测试通过了。

  3. 如果我将所有类移动到默认包中,测试就会通过!如果所有类都保留在包foo中,则测试失败。

  4. 以下是我项目中包含的文件。我上面链接的ZIP是一个包含所有这些内容的小型Maven项目。

    我还将此问题发布到JMock开发人员列表中。如果我在那里收到答案,我会更新这个问题(反之亦然)。


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

1 个答案:

答案 0 :(得分:0)

为未来的读者提供更新....

目前,我认为这是JMock中的一个错误。我已经在JMock github页面上提交了它:https://github.com/jmock-developers/jmock-library/issues/43。还没有回复(也不是我对邮件列表的评论)。

我已经切换到Mockito,它可以毫无错误地处理完全相同的情况。