我正在开发一个方便的函数,它可以跟踪执行操作所需的时间,并将其发送到我们的监控服务。我们的想法是尽可能减少对我们的主代码库的干扰,所以我想我应该让它接受一个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>,但都无济于事。我真的不想为每种类型的供应商都这样做。
发布于 2020-02-10 00:08:28
将你的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());
}https://stackoverflow.com/questions/60138415
复制相似问题