The JUnit test in the example project is attempting to mock the ForwardingServlet
class. But, in this scenario with an embedded Jetty web server, there are actually two instances of this class, both loaded in the same JVM but through different classloaders.
The first instance of the class is loaded by the regular classloader, through which classes are loaded from the thread that starts the JUnit test runner (AppClassLoader
). So, when ForwardingServlet
appears in test code, it is the one defined in this classloader. This is the class given to JMockit to mock, which is exactly what happens.
But then, a copy of ForwardingServlet
is loaded inside the deployed web app (from the ".class" file in the file system, so not affected by the mocking as applied by JMockit, which is in-memory only), using Jetty's WebAppClassLoader
. This class is never seen by JMockit.
There are two possible solutions to this issue:
Somehow get the class object loaded by
WebAppClassLoader
and then mock it by calling theMockUp(Class)
constructor.Configure the Jetty server so that it does not use a custom classloader for the classes in the web app.
The second solution is the easiest, and can be done simply by adding the following call on the ContextHandler
object created from the WebArchive
object, before setting the handler into the Jetty Server
object:
handler.setClassLoader(ClassLoader.getSystemClassLoader());
I tested this and it worked as expected, with the @Mock doGet(...)
method getting executed instead of the real one in ForwardingServlet
.