【问题标题】:How to mock a Consumer argument using EasyMock with PowerMock如何使用 EasyMock 和 PowerMock 模拟消费者参数
【发布时间】:2019-09-23 19:37:48
【问题描述】:

我有一个需要模拟消费者参数的测试场景。

在下面的代码中,startTracer 是要测试的方法。

class TracerService {

    private TracerController tracerController;

    public void startTracer(String tracerName, Object param1) {
        if (attendStartConditions(tracerName, param1)) {
            executeOnTracerControllerScope(tracerController -> tracerController.startTracer(param1));
        }
    }
    ...
}

基本上,我想测试tracerController.startTracer(param1) 是否接收param1 作为参数。

Capture<Object> method1Param1 = newCapture();
tracerController.startTracer(capture(method1Param1));
expectLastCall().once();
...
tracerService.startTracer("TEST", "value1");
assertThat(method1Param1.getValue()).isEqualsTo("value1");

如何在不调用其内部代码的情况下为 executeOnTracerControllerScope 执行 tracerController.startTracer 配置 EasyMock/PowerMock?

【问题讨论】:

    标签: powermock easymock


    【解决方案1】:

    tracerController 是一个模拟。所以startTracer 不会被调用。正如现在定义的那样,它什么也不做。执行您所要求的代码应该是这样的:

    Capture<Object> method1Param1 = newCapture();
    tracerController.startTracer(capture(method1Param1)); // no need for the expect, it's the default
    replay(tracerController);
    // ...
    tracerService.startTracer("TEST", "value1");
    assertThat(method1Param1.getValue()).isEqualsTo("value1");
    

    当然,attendStartConditionsexecuteOnTracerControllerScope 将被真正调用。

    根据您的评论,如果您想模拟 executeOnTracerControllerScope,您将执行以下代码。但是,您的 lambda 将不再被调用。所以你将无法验证参数。

    public class MyTest {
        @Test
        public void test() {
            TracerController tracerController = mock(TracerController.class);
            TracerService service = partialMockBuilder(TracerService.class)
                    .withConstructor(tracerController)
                    .addMockedMethod("executeOnTracerControllerScope")
                    .mock();
            replay(tracerController);
    
            service.startTracer("tracer", "param");
        }
    }
    
    class TracerService {
    
        private final TracerController tracerController;
    
        public TracerService(TracerController tracerController) {
            this.tracerController = tracerController;
        }
    
        public boolean attendStartConditions(String tracerName, Object param1) {
            return true;
        }
    
        public void executeOnTracerControllerScope(Consumer<TracerController> tracer) {
            tracer.accept(tracerController);
        }
    
        public void startTracer(String tracerName, Object param1) {
            if (attendStartConditions(tracerName, param1)) {
                executeOnTracerControllerScope(tracerController -> tracerController.startTracer(param1));
            }
        }
    
    }
    
    interface TracerController {
        void startTracer(Object param1);
    }
    

    【讨论】:

    • 好的,但除此之外,假设我不想从 TracerService 创建部分模拟(以测试startTrace 方法)。在这种情况下,有一些方法可以模拟方法executeOnTracerControllerScope?