Что ломается первым, Mockito или Java Generics? - PullRequest
1 голос
/ 09 февраля 2020

У меня есть удобная функция, над которой я работаю, которая отслеживает время, необходимое для выполнения операции, и отправляет ее в нашу службу мониторинга. Идея заключалась в том, чтобы быть минимально навязчивым к нашей основной кодовой базе, насколько это возможно, поэтому я подумал, что мне понадобится Runnable или Supplier<T> и выполнит это сам.

  public <T> T recordElapsedTime(
      Builder measurementBundleBuilder,
      DistributionMetric distributionMetric,
      Supplier<T> operation) {
    final Stopwatch stopwatch = stopwatchProvider.get();

    stopwatch.start();
    final T result = operation.get();
    stopwatch.stop();

    record(
        measurementBundleBuilder
            .addMeasurement(distributionMetric, stopwatch.elapsed().toMillis())
            .build());
    return result;
  }

Вы называете это например,

    List<WorkspaceResponse> workspaces =
        logsBasedMetricService.recordElapsedTime(
            MeasurementBundle.builder().addTag(MetricLabel.OPERATION_NAME, "getWorkspaces"),
            DistributionMetric.WORKSPACE_OPERATION_TIME,
            workspaceService::getWorkspaces);

И есть работающая версия, которая такая же, но возвращает void.

Итак, самое интересное начинается, когда мне приходится высмеивать сервис, выставляющий эту функцию.

Они идут по общим путям кода, так что много тестовой очистки. Методы ложных объектов по умолчанию возвращают null, так что вы потеряете созданное рабочее пространство или любой другой ценный объект.

Теперь у меня есть насмешка:

    doAnswer(invocation -> ((Supplier) invocation.getArgument(2)).get())
        .when(mockLogsBasedMetricService)
        .recordElapsedTime(
            any(MeasurementBundle.Builder.class),
            any(DistributionMetric.class),
            ArgumentMatchers.<Supplier<Workspace>>any());

Так что Вопрос в том, могу ли я высмеивать это поведение для любого аргумента Supplier<T>? Я пытался просто использовать голые Supplier и Supplier<Object>, но безрезультатно. Я действительно не хочу делать это для каждого типа поставщика.

1 Ответ

3 голосов
/ 09 февраля 2020

Поместите ваш doAnswer в метод, это должно работать в общем случае:

<T> void setupAnswer (/* whatever args */) {
  doAnswer(invocation -> ((Supplier<T>) invocation.getArgument(2)).get())
      .when(mockLogsBasedMetricService)
      .recordElapsedTime(
          any(MeasurementBundle.Builder.class),
          any(DistributionMetric.class),
          ArgumentMatchers.<Supplier<T>>any());
}
...