我不熟悉在java中编写测试,似乎无法测试是否调用了类的方法。
我正在向datadog发送指标,并希望在代码中测试是否调用了另一个类的函数。
它说我需要先嘲笑,但我无法让它发挥作用。
MetricRecorder.java
import com.timgroup.statsd.StatsDClient;
import com.timgroup.statsd.NonBlockingStatsDClient;
import com.google.common.base.Preconditions;
public class MetricRecorder {
private final String namespace;
private final static StatsDClient metrics = new NonBlockingStatsDClient(
"my.prefix",
"localhost",
8125,
new String[] {"tag:value"}
);
public MetricRecorder(String namespace) {
Preconditions.checkNotNull(namespace);
this.namespace = namespace;
}
public void inc(String metricName) {
this.inc(metricName, 1);
}
public void inc(final String metricName, final long value) {
Preconditions.checkNotNull(metricName);
try {
metrics.recordHistogramValue(MetricRecorder.name(namespace, metricName), value);
} catch (Exception e) {
logger.warn("Unable to record metric {} due to :", metricName, e);
}
}
...
}
MetricRecorderTest.java
public class MetricsRecorderTest {
@Test
public void metricsRecorderTest() {
MetricRecorder recorder = new MetricRecorder("dev");
recorder.inc("foo", 1);
verify(recorder.metrics, times(1)).recordHistogramValue(eq("dev.foo"), 1);
}
}
当我运行测试时,我得到这个=> org.mockito.exceptions.misusing.NotAMockException: 传递给verify()的参数是NonBlockingStatsDClient类型,不是模拟的!
如果调用了recordHistogramValue,我应该如何测试,如果有的话,是什么参数?
答案 0 :(得分:1)
由于看起来StatsDClient
是某种类型的接口,它会使您的测试工作更容易,只需将此依赖项注入您的对象。即使你没有使用像Spring或Guice这样的IoC容器,你仍然可以通过构造函数传递它的实例来控制它。
public MetricRecorder(String namespace, StatsDClient client) {
Preconditions.checkNotNull(namespace);
Preconditions.checkNotNull(client);
this.namespace = namespace;
this.client = client;
}
这将使您的测试更简单,因为您实际需要做的就是模拟测试期间传入的对象。
现在,它失败的原因是因为你new
了实例,并且Mockito(在当前配置中)没有能够模拟新建的实例。老实说,这个设置会使测试变得更简单,你应该只需要在一个区域配置你的客户端。
@RunWith(MockitoJUnitRunner.class)
public class MetricsRecorderTest {
@Test
public void metricsRecorderTest() {
StatsDClient dClientMock = Mockito.mock(StatsDClient.class);
MetricRecorder recorder = new MetricRecorder("dev", dClientMock);
recorder.inc("foo", 1);
verify(recorder.metrics).recordHistogramValue(eq("dev.foo"), 1);
}
}
答案 1 :(得分:0)
你这里弄错了。您没有使用模拟框架来测试您正在测试的"类#34;。
您使用模拟框架来创建模拟对象;然后你把它传给你正在测试的课程"在测试用例中。那么你正在测试的代码"调用模拟对象上的方法;并通过控制返回值(或通过验证模拟发生的事情);这就是你编写测试用例的方法。
因此,MetricRecorder的测试用例不会模拟MetricRecorder;它应该模拟StatsDClient类;正如Makoto建议的那样;使用依赖注入将该类的对象放入MetricRecorder。
此外:基本上写作"可测试"代码是需要实践的东西。如果您真的想要从事这项业务,我全心全意地建议您观看这些videos。他们都是;真的(值得每一秒!)。