当函数的代码作为方法参数传递时,如何测试?

时间:2019-11-13 13:20:20

标签: java lambda jmockit

是否可以测试在方法process中传递的用lambda函数编写的代码?

@AllArgsConstructor
public class JsonController {
    private final JsonElementProcessingService jsonElementProcessingService;
    private final JsonObjectProcessingService jsonObjectProcessingService;
    private final JsonArrayProcessingService jsonArrayProcessingService;

    public void process(String rawJson) {
        jsonElementProcessingService.process(json -> {
            JsonElement element = new JsonParser().parse(json);
            if (element.isJsonArray()) {
                return jsonArrayProcessingService.process(element.getAsJsonArray());
            } else {
                return jsonObjectProcessingService.process(element.getAsJsonObject());
            }
        }, rawJson);
    }
}

由于lambda是惰性的,因此在我调用Function::apply时不会调用(JsonController::process)函数,那么有什么方法可以检查jsonArrayProcessingService::process是否被调用吗?

@RunWith(JMockit.class)
public class JsonControllerTest {
    @Injectable
    private JsonElementProcessingService jsonElementProcessingService;
    @Injectable
    private JsonObjectProcessingService jsonObjectProcessingService;
    @Injectable
    private JsonArrayProcessingService jsonArrayProcessingService;
    @Tested
    private JsonController jsonController;

    @Test
    public void test() {
        jsonController.process("[{\"key\":1}]");
        // how check here that jsonArrayProcessingService was invoked?
    }
}

2 个答案:

答案 0 :(得分:2)

只需将其转换为方法即可使其可测试(并且可读):

public void process(String rawJson) {
    jsonElementProcessingService.process(this::parse, rawJson);
}

Object parse(String json) {
    JsonElement element = new JsonParser().parse(json);
    if (element.isJsonArray()) {
        return jsonArrayProcessingService.process(element.getAsJsonArray());
    } else {
        return jsonObjectProcessingService.process(element.getAsJsonObject());
    }
}

我个人遵循的相关指导原则是:

  • 只要我的lambda需要大括号,请将其转换为方法
  • 组织代码,以便 可以进行单元测试

您可能需要更改parse方法的返回类型,以匹配您的处理服务(未显示)返回的任何内容。

答案 1 :(得分:1)

鉴于其相对基本的重定向逻辑,您是否只是想确认调用了哪个@Injectable

  @Test
  public void test() {
    jsonController.process("[{\"key\":1}]");

    new Verifications() {{
      jsonArrayProcessingService.process(withInstanceOf(JsonArray.class));
    }};
  }