模拟 InfluxDB 客户端以测试 MetricCollector class

Mock InfluxDB client to test a MetricCollector class

我有一个在 InfluxDB 上存储数据的指标收集器,我想测试存储该指标的方法。我正在尝试,但无法模拟 InfluxDB 客户端。我不想在测试环境上点一个真实的InfluxDB

到目前为止我所取得的一切都是一些 "null pointer exceptions" 并且连接被拒绝。

这是我的测试(使用 TestNG)。我究竟做错了什么?

    @Test
    public void validateMetrics() {
        String influxHost = "http://localhost";
        String credentials = "admin:admin";
        String influxDatabaseName = "testDataBase";
        influxDB = InfluxDBFactory.connect(influxHost, credentials.split(":")[0], credentials.split(":")[1]);

        MetricsCollector metricsCollector = null;

        try {
            String hostName = "test-server-01";
            int statusValue = 1;
            metricsCollector = new MetricsCollector(influxDB);


            BatchPoints metrics = metricsCollector.initBatchPoint(influxDatabaseName); 
            Point point = metricsCollector.setMetric(hostName, "status", statusValue);
            metrics = metricsCollector.addToMetrics(metrics, point);

            Assert.assertTrue(metrics.getPoints().get(0).lineProtocol().contains(hostName));
            Assert.assertTrue(metrics.getPoints().get(0).lineProtocol().contains("status=" + statusValue));
        } finally {
           if (metricsCollector != null) {
                metricsCollector.closeConnection();
            }
        }
    }

我怀疑您不能模拟 InfluxDB 客户端的原因是它是由静态方法创建的:InfluxDBFactory.connect()。要模拟这个,你需要 PowerMock.

像这样:

@PrepareForTest({InfluxDBFactory.class})
public class ATestClass {

    @Test
    public void validateMetrics() {
        // this allows you to mock static methods on InfluxDBFactory
        PowerMockito.mockStatic(InfluxDBFactory.class);

        String influxHost = "http://localhost";
        String credentials = "admin:admin";
        String influxDatabaseName = "testDataBase";

        InfluxDB influxDB = Mockito.mock(InfluxDB.class);

        // when the connect() method is invoked in your test run it will return a mocked InfluxDB rather than a _real_ InfluxDB
        PowerMockito.when(InfluxDBFactory.connect(influxHost, credentials.split(":")[0], credentials.split(":")[1])).thenReturn(influxDB);

        // you won't do this in your test, I've only included it here to show you that InfluxDBFactory.connect() returns the mocked instance of InfluxDB
        InfluxDB actual = InfluxDBFactory.connect(influxHost, credentials.split(":")[0], credentials.split(":")[1]);
        Assert.assertSame(influxDB, actual);

        // the rest of your test
        // ...
    }
} 

注意:描述了 TestNG、Mockito 和 PowerMock 的特定兼容性要求here and here

我完全误解了 mockito 的工作原理。这是我的固定代码:

    @Mock private InfluxDB influxDB;
    @Test
    public void validateMetrics() {
        MetricsCollector metricsCollector = null;
        String influxHost = "http://localhost";
        String credentials = "admin:admin";
        String influxDatabaseName = "testDataBase";

        influxDB = InfluxDBFactory.connect(influxHost, credentials.split(":")[0], credentials.split(":")[1]);

       try {
            String hostName = "test-server-01";
            int statusValue = 1;
            metricsCollector = new MetricsCollector(influxDB);

            BatchPoints metrics = metricsCollector.initBatchPoint(influxDatabaseName); 
            Point point = metricsCollector.setMetric(hostName, "status", statusValue);
            metrics = metricsCollector.addToMetrics(metrics, point);

            Assert.assertTrue(metrics.getPoints().get(0).lineProtocol().contains(hostName));
            Assert.assertTrue(metrics.getPoints().get(0).lineProtocol().contains("status=" + statusValue));
       } finally {
           if (metricsCollector != null) {
                metricsCollector.closeConnection();
            }
       }
    }

是的,添加了那个简单的 "mock" 注释并且一切正常。