Capturing a Runnable with JMockit and Executing It

At work, we use JMockit. I’m far more comfortable with Mockito, which made it very easy for me to understand how to capture a Runnable passed in, execute it, and then check that certain calls were made. I have always struggled with doing that with JMockit, but I think I finally figured it out:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class DemoWithRunnable {
    public interface Dependency {
        int someMethod();
        void otherMethod(int i);
    }

    private final Dependency dependency;
    private final ExecutorService executor;

    public DemoWithRunnable(Dependency d, ExecutorService e) {
        this.dependency = d;
        this.executor = e;
    }

    public void doSomething() {
        executor.submit(new Runnable() {
            public void run() {
                int i = dependency.someMethod();
                dependency.otherMethod(i);
            }
        });
    }
}

What I want to do here in a test, of course, is:

  1. Check that we call ExecutorService.submit
  2. Run the Runnable that was passed to submit
  3. Mock someMethod and return some value, and
  4. Check that otherMethod was called with the returned value.

And I think this is how you do it in JMockit:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public class DemoWithRunnableTest {
    @Mocked DemoWithRunnable.Dependency d;

    @Mocked ExecutorService e;

    @Test
    public void testDoSomething() {
        DemoWithRunnable impl = new DemoWithRunnable(d, e);

        impl.doSomething();

        List<Runnable> r = new ArrayList<>();

        // capture the Runnable
        new Verifications() {{
            e.submit(withCapture(r));
        }};

        // add new expectations for code in the Runnable, with return values
        new Expectations() {{
            d.someMethod(); result = 42;
        }};

        // run the Runnable
        r.get(0).run();

        // verifications for the code in the Runnable
        new Verifications() {{
            d.otherMethod(42);
        }};
    }
}

About Mathias

Software development engineer. Principal developer of DrJava. Recent Ph.D. graduate from the Department of Computer Science at Rice University.
This entry was posted in Programming. Bookmark the permalink.

Leave a Reply