Mockito - 测试一个类的方法是否被调用
我是用java编写测试的新手,似乎无法测试某个类的方法是否被调用。Mockito - 测试一个类的方法是否被调用
我正在发送指标给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: 参数传递给验证( )是NonBlockingStatsDClient类型,不是模拟的!
任何想法,如果我应该测试recordHistogramValue是否被调用,如果是的话,什么参数?
由于它看起来像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);
}
}
你在这里弄错了。您不使用嘲讽框架来测试您的“正在测试的课程”。
您使用嘲讽框架创建嘲笑对象;然后在测试用例中将其传递给“正在测试的课程”。然后你的“测试代码”在模拟对象上调用方法;并通过控制返回的值(或通过验证你的模拟会发生什么);这就是你如何编写测试用例。
因此,您的MetricRecorder测试用例不会模拟MetricRecorder;它应该模拟StatsDClient类;正如Makoto所建议的那样;使用依赖项注入将该类的对象放入MetricRecorder中。另外:基本上写“可测试”代码是需要实践的东西。如果您认真对待这项业务,我衷心推荐您观看这些videos。他们全部;真的(值得每秒!)。
你是否建议我除了我已经有的构造函数外还使用这个构造函数模式?我认为这将工作在技术上....只有其他变化,我将不得不做的是公共最终静态StatsDClient指标私人静态StatsDClient指标...它必须公开测试recorder.metrics,它不能是最终的无论是。 –