【问题标题】:MQTT Client testing with junit使用 junit 进行 MQTT 客户端测试
【发布时间】:2018-07-17 13:49:37
【问题描述】:

我正在尝试测试使用 MQTT 客户端的 Spring-Boot 应用程序。我想测试几个类似这些区域的属性:

  • 是否正确处理连接失败
  • 是否正确处理连接成功
  • 是否正确解析消息负载(json?)
  • 它是否正确处理格式错误的负载。

(来源How do I write tests for an MQTT client?

所以,我的 MQTT 客户端代码是(简化的):

@Component
public class MQTTController implements MqttCallback {

    MqttClient client;

    @Value("${spring.mqtt.serverURI}")
    private String serverURI;

    @Value("${spring.mqtt.port}")
    private String serverPort;
    
    @Bean
    private MqttClient receiveData() {
        try{
            client = new MqttClient(serverURI + ":" + serverPort, "Receiver");
            client.connect();
            client.setCallback(this);
            client.subscribe("someTopic");
            return client;
        }
        catch(Exception e){
            log.error("MQTT ERROR");
            log.error(e.toString());
        }
        return null;
    }

    public void connectionLost(Throwable cause) {
    }

    public void messageArrived(String topic, MqttMessage message) throws Exception {
        someActionWithTheData(message.ToString());
    }

    public void deliveryComplete(IMqttDeliveryToken token) {
    }
}

主要问题是在测试期间,我没有 MQTT Broker。我的代理只能在 docker 容器上使用,我必须在不使用它的情况下测试这个类。 我在 mqtt 包org.eclipse.paho.client.mqttv3 中搜索了一些用于测试的嵌入式代理,但我一无所获。而且我不想仅仅为了一个单元测试向我的项目添加另一个依赖项。

那么,有没有一种方法可以在不向 MQTT 代理添加依赖项的情况下测试此类?如果没有,最简单的方法是什么?

【问题讨论】:

    标签: java unit-testing spring-boot mqtt


    【解决方案1】:

    最佳做法是将基础架构的代码部分与业务代码分开。这样,您可以编写单元测试来仅测试应用程序的业务。 在您的示例中,您可以简单地编写一个单元测试来测试方法messageArrived。例如,

    @Test
    public void test_on_message() {
    
        MQTTController controller = new MQTTController();
    
        MqttMessage message = new MqttMessage();
    
        controller.messageArrived("my_topic", message);
    
        ...
    }
    

    您还可以使用 Mockito 来模拟 MqttMessage 及其方法 ToString

    然后,您还可以通过在测试中提供嵌入式代理来编写集成测试。我认为最好的方法是使用Testcontainers。您可以从 docker 映像创建代理 MQTT。 在此示例中,它从官方 docker image 创建了一个 Mosquitto 代理。

    @ClassRule
    public static GenericContainer mosquitto = new GenericContainer("eclipse-mosquitto:1.4.12")
        .withExposedPorts(1883, 9001);
    

    【讨论】:

      【解决方案2】:

      我认为您正在寻找一个模拟框架。我来自 C++,但我认为这也是适用的:基本上,您为所有关联(您应该是 MqttClient)和每个成员函数注入一个模拟对象,您使用框架的模拟功能,以便您只能在特定的测试用例中描述此函数的行为(例如,指定要检查的参数值)。

      经过一番研究,我发现: https://dzone.com/articles/spring-boot-unit-testing-and-mocking-with-mockito

      Mockito 段落很好地介绍了模拟功能和基于测试的行为。

      希望对您有所帮助,祝您有美好的一天!

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-01-07
        • 2019-11-04
        • 1970-01-01
        • 2018-05-12
        相关资源
        最近更新 更多