0

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>
Community
  • 1
  • 1
Mallox
  • 1,469
  • 12
  • 13
  • Could you show a test which reproduces the exception? Or is it enough to have any signed jar in the classpath, while running a test which mock a class from the jar? – Rogério Aug 13 '13 at 13:29
  • I'm guessing that any jar that has components that check the signature will cause this problem. – Mallox Aug 13 '13 at 23:45
  • I used the code above (both the test class and the pom.xml fragment) in a test, but there was no error. Also, `OpenIDAuthenticationProvider` is from Spring Security but this dependency is not included above. The same applies to the `FilterRegistration` interface, which is from another Jetty dependency. If you are willing, open a new issue in the JMockit issue tracker, with more complete information. – Rogério Aug 15 '13 at 00:25
  • Acutally no, OpenIDAuthenticationProvider is our custom implementation, we don't use spring in our project. javax.servlet.FilterRegistration is part of the javax.servlet api, which is defined below the jetty instance. Thanks for the offer, but I actually prefer the fix below, as it's not only JMockIt that can affect the signature, it's just one of cases where this occurs. – Mallox Aug 15 '13 at 06:47
  • And my guess why you're not getting an exception is probably because the spring OpenIDAuthenicationProvider has an empty default constructor, which is why mocking it with another empty one would probably not modify the resulting jar signature. Our implementation does stuff in the constructor, mocking is therefor a change that can be registered. – Mallox Aug 15 '13 at 06:55
  • Ah, ok. I had googled `OpenIDAuthenticationProvider` and found it in Spring, so I thought that was the one. As for `javax.servlet.FilterRegistration`, it exists only in Servlet 3.0+, not in 2.5. Anyway, I will try it again. – Rogério Aug 15 '13 at 15:19
  • Ah okay, well that also explains why putting the servlet-api dependency before jetty causes a signing failure. Jetty itself must provide a transient reference to servlet-api 3.0 (kinda obvious since it's implementing it ^^) – Mallox Aug 16 '13 at 08:28

1 Answers1

4

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.

Mallox
  • 1,469
  • 12
  • 13