使用 junit 进行 MQTT 客户端测试

Gaz*_*ouu 1 java unit-testing mqtt spring-boot

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

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

(来源如何为 MQTT 客户端编写测试?

所以,我的 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) {
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

vic*_*let 5

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

@Test
public void test_on_message() {

    MQTTController controller = new MQTTController();

    MqttMessage message = new MqttMessage();

    controller.messageArrived("my_topic", message);

    ...
}
Run Code Online (Sandbox Code Playgroud)

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

然后,您还可以通过在测试中提供嵌入式代理来编写集成测试。我认为最好的方法是使用Testcontainers。您可以从 docker 映像创建代理 MQTT。在这个例子中,它会创建一个Mosquitto从它的官方泊坞窗经纪人图像

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