Search code examples
javaunit-testingjmockit

Unable to mock static invocations using JMockit


I am having difficulty mocking static invocations. I don't know what I am doing wrong.

My stripped down source code:

import javax.servlet.http.HttpServletRequest;

import org.apache.struts2.ServletActionContext;

public class OptionsBusinessEventFormatter {

  void process() {
    System.out.println("Testing testing ");
    HttpServletRequest request = ServletActionContext.getRequest();
    System.out.println("request = " + request);
    System.out.println(request.getParameter("returnedURI"));
  }
}

My unit test

@RunWith(JUnit4.class)
public class OptionsBusinessEventFormatterTest {

  private OptionsBusinessEventFormatter optionsBusinessEventFormatter;

  @Before
  public void setUp() throws Exception {
     this.optionsBusinessEventFormatter = new OptionsBusinessEventFormatter();
  }

  @Test
  public void process_HappyPath() {
      final MockHttpServletRequest request = new MockHttpServletRequest();
      Map<String, String> map = new HashMap<>();
      request.setParameters(map);
      new Expectations() {
          @Mocked ServletActionContext servletContext;
          {
              ServletActionContext.getRequest();
              result = request;
          }
      };
      this.optionsBusinessEventFormatter.process();
  }
}

I get the following error.

java.lang.IllegalStateException: Native library for Attach API not available in this JRE
    at mockit.internal.startup.AgentLoader.getVirtualMachineImplementationFromEmbeddedOnes(AgentLoader.java:88)
    at mockit.internal.startup.AgentLoader.loadAgent(AgentLoader.java:47)
    at mockit.internal.startup.AgentInitialization.loadAgentFromLocalJarFile(AgentInitialization.java:27)
    at mockit.internal.startup.Startup.initializeIfPossible(Startup.java:252)
    at org.junit.runner.Runner.<clinit>(Runner.java:22)
    at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:61)
    at org.junit.internal.builders.AllDefaultPossibilitiesBuilder.runnerForClass(AllDefaultPossibilitiesBuilder.java:26)
    at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:59)
    at org.junit.internal.requests.ClassRequest.getRunner(ClassRequest.java:26)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.<init>(JUnit4TestReference.java:33)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestClassReference.<init>(JUnit4TestClassReference.java:25)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestLoader.createTest(JUnit4TestLoader.java:48)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestLoader.loadTests(JUnit4TestLoader.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:452)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Caused by: java.lang.UnsatisfiedLinkError: no attach in java.library.path
    at java.lang.ClassLoader.loadLibrary(Unknown Source)
    at java.lang.Runtime.loadLibrary0(Unknown Source)
    at java.lang.System.loadLibrary(Unknown Source)
    at sun.tools.attach.WindowsVirtualMachine.<clinit>(WindowsVirtualMachine.java:185)
    at mockit.internal.startup.AgentLoader.getVirtualMachineImplementationFromEmbeddedOnes(AgentLoader.java:66)
    ... 16 more
java.lang.NoClassDefFoundError: Could not initialize class org.junit.internal.runners.ErrorReportingRunner
    at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:61)
    at org.junit.internal.requests.ClassRequest.getRunner(ClassRequest.java:26)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.<init>(JUnit4TestReference.java:33)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestClassReference.<init>(JUnit4TestClassReference.java:25)

I even tried using MockUp instance as given below

  public class MockServletActionContext extends MockUp<ServletActionContext> {

      private final MockHttpServletRequest request;

      public MockServletActionContext(MockHttpServletRequest request) {
          this.request = request;
      }

      @Mock void $init() {}

      @Mock
      public HttpServletRequest getRequest() {
          return this.request;
      }
  }

I get the same error.


Solution

  • I had to the following things to get the execution to run from Eclipse

    Debug > Create new Launch Config> Select a Test Case >  Arguments > VM Arguments > Path to jMockit Jar.
    

    With Maven

     <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>2.5</version>
                <dependencies>
                    <dependency>
                        <groupId>org.apache.maven.surefire</groupId>
                        <artifactId>surefire-junit47</artifactId>
                        <version>2.17</version>
                    </dependency>
                </dependencies>
                <configuration>
                    <argLine>
                        -javaagent:"${settings.localRepository}"/com/googlecode/jmockit/jmockit/${jmockit.version}/jmockit-${jmockit.version}.jar
                    </argLine>
                    <redirectTestOutputToFile>true</redirectTestOutputToFile>
                </configuration>
            </plugin>
        </plugins>
    </build>
    

    This worked for me.