JMockit:模拟接口的所有实现

时间:2014-02-26 12:23:36

标签: unit-testing jmockit

是否可以模拟接口的所有实现?

我想模拟WatchService接口,如下所示

公共类ServiceTest {

@Test
public void callTest(
        @Capturing
        @Injectable
        final WatchService ws
) throws Exception {
    final CountDownLatch latch = new CountDownLatch(1);
    new MockUp<ServiceTest>() {
        @Mock(invocations = 1)
        public void onChange() {
            latch.countDown();
        }
    };

    new NonStrictExpectations() {
        {
            ws.take();
            result = new Delegate() {
                WatchKey take(Invocation inv) {
                    System.out.println("> " + inv.getInvokedInstance());

                    try {
                        new File("target/newFile").createNewFile();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }

                    return inv.proceed();
                }
            };
        }
    };

    final Thread thread = new Thread() {
        @Override
        public void run() {

            final Path target = Paths.get("target");
            final FileSystem fs = target.getFileSystem();

            try {
                try (WatchService watcher = fs.newWatchService()) {
                    target.register(watcher, ENTRY_CREATE);

                    while (!Thread.currentThread().isInterrupted()) {
                        WatchKey take = watcher.take();
                        onChange();
                        System.out.println("take " + take);
                    }

                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    };

    thread.start();


    assertTrue("", latch.await(5, TimeUnit.SECONDS));
    thread.interrupt();

}

private void onChange() {
    System.out.println("CHANGE");
}

我该如何实现?

1 个答案:

答案 0 :(得分:1)

您可以在模拟字段或接口类型的模拟参数上使用@Capturing注释。下面我们有一个完整的示例测试(减去进口)。

public class CapturingAndProceedingTest {
    static class WatchKey { String key; WatchKey(String k) {key = k;} }
    public interface WatchService { public abstract WatchKey take(); }
    static class WatchServiceImpl1 implements WatchService {
        @Override public WatchKey take() { return new WatchKey("Abc"); }
    }
    static class WatchServiceImpl2 implements WatchService {
        @Override public WatchKey take() { return new WatchKey("123"); }
    }

    @Test
    public void mockAllImplementationsOfAnInterface(
        @Capturing  // so that all implementing classes are mocked
        @Injectable // so that Invocation#proceed() is supported
        final WatchService watchService
    ) {
        final List<WatchService> services = new ArrayList<>();

        // Record an expectation that will match all calls to 
        // WatchService#take(), on any class implementing the interface.
        new NonStrictExpectations() {{
            watchService.take();
            result = new Delegate() {
                WatchKey take(Invocation inv) throws IOException {
                    // Do something here...
                    WatchService service = inv.getInvokedInstance();
                    services.add(service);

                    // ...then proceed to the real implementation.
                    return inv.proceed();
                }
            };
        }};

        // Instantiate and use different implementations of the interface.
        WatchServiceImpl1 impl1 = new WatchServiceImpl1();
        assertEquals("Abc", impl1.take().key);
        WatchServiceImpl2 impl2 = new WatchServiceImpl2();
        assertEquals("123", impl2.take().key);

        assertEquals(Arrays.asList(impl1, impl2), services);
        System.out.println(services);
    }
}

有关更多示例,请参阅JMockit Tutorial