Mockito - 测试是否调用了类的方法

时间:2016-08-21 03:33:55

标签: java unit-testing junit mockito

我不熟悉在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,我应该如何测试,如果有的话,是什么参数?

2 个答案:

答案 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。他们都是;真的(值得每一秒!)。