当运行JMockIt并尝试模拟从已签名的jar加载的testng中的实例时,出现以下错误(在这种情况下为码头服务器):

FAILED CONFIGURATION: @BeforeClass startServer
java.lang.SecurityException: class "javax.servlet.FilterRegistration"'s signer information does not match signer information of other classes in the same package
    at java.lang.ClassLoader.checkCerts(ClassLoader.java:943)
    at java.lang.ClassLoader.preDefineClass(ClassLoader.java:657)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:785)
    at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
    at java.net.URLClassLoader.defineClass(URLClassLoader.java:449)
    at java.net.URLClassLoader.access$100(URLClassLoader.java:71)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:361)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
    ...


pom中的依赖关系顺序是正确的,并且在没有模拟的情况下测试也可以正常运行。因此,Java SecurityException: signer information does not match中的提示在这里无济于事。

有解决方法吗?



这是一个示例测试,应该会产生错误。在这种情况下,我们启动整个容器进行集成测试:

public class MyServletTest {
    private final Server server = new Server(PORT);
    private MockUp<OpenIDAuthenticationProvider> openIDap;

    @BeforeClass
    public void startServer() throws Exception {
        final ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
        context.setContextPath("/");
        context.addServlet(MyServlet.class, "/my/*");
        this.server.setHandler(context);
        this.server.start();
        this.openIDap = new MockUp<OpenIDAuthenticationProvider>() {
            @Mock
            void $init(final UserDAO userDao) {}
        };
    }

    @Test
    ...
}


OpenIDAuthenticationProvider是从MyServlet内部调用的,并在启动过程中实例化,尽管我不确定这是否重要。

pom.xml中的相应部分如下所示:

<dependencies>
    <dependency>
        <groupId>org.eclipse.jetty</groupId>
        <artifactId>jetty-servlet</artifactId>
        <version>9.0.3.v20130506</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.eclipse.jetty</groupId>
        <artifactId>jetty-server</artifactId>
        <version>9.0.3.v20130506</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>servlet-api</artifactId>
        <version>2.5</version>
        <scope>provided</scope>
    </dependency>
</dependencies>

最佳答案

一种方法是使用JMockIt停用证书检查。由于JMockIt(和其他Mocking框架)通过检测工作,因此可以修改任何类。这是一个有关如何模拟ClassLoader部分的示例,这会引起麻烦:

@BeforeSuite
public void deactivateCertChecker() {
    new MockUp<ClassLoader>() {
        @Mock
        void checkCerts(final String name, final CodeSource cs) {}
    };
}


请注意,这并不是实际运行存在签名问题的程序的解决方案,因为只有在测试了模拟后,该效果才在测试运行期间可用。

关于java - JMockIt安全异常签名者信息不匹配,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/18198561/

10-10 07:06