When running JMockIt and trying to mock an instance in testng that is loaded from a signed jar I get an error along the lines of (in this case of a jetty server):

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)
    ...

The dependency order in the pom is correct, and without the mocks the tests run fine. So the tips from Java SecurityException: signer information does not match do not help here.

Is there a workaround?


Here is a sample test up, that should produce the error. In this case we start an entire container for an integration test:

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

The OpenIDAuthenticationProvider is called from within MyServlet and instantiated during startup, although I'm not sure that even matters.

the corresponding part in the pom.xml looks like this:

<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>
有帮助吗?

解决方案

One way is to use JMockIt to deactivate the certificate check. Since JMockIt (and other Mocking Frameworks) work via instrumentation, any class can be modified. Here is an example as to how to mock the part of the ClassLoader, that causes the troubles:

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

Mind you though, that this is not a fix for actually running a program that has signing issues, as the effect is only available during test runs, when mocking has been instrumented.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top