public static MqttMessage newMessage(MqttFixedHeader mqttFixedHeader, Object variableHeader, Object payload) {
        switch (mqttFixedHeader.messageType()) {
            case CONNECT :
                return new MqttConnectMessage(
                        mqttFixedHeader,
                        (MqttConnectVariableHeader) variableHeader,
                        (MqttConnectPayload) payload);

            case CONNACK:
                return new MqttConnAckMessage(mqttFixedHeader, (MqttConnAckVariableHeader) variableHeader);

            case SUBSCRIBE:
                return new MqttSubscribeMessage(
                        mqttFixedHeader,
                        (MqttMessageIdVariableHeader) variableHeader,
                        (MqttSubscribePayload) payload);

            case SUBACK:
                return new MqttSubAckMessage(
                        mqttFixedHeader,
                        (MqttMessageIdVariableHeader) variableHeader,
                        (MqttSubAckPayload) payload);

            case UNSUBACK:
                return new MqttUnsubAckMessage(
                        mqttFixedHeader,
                        (MqttMessageIdVariableHeader) variableHeader,
                        (MqttUnsubAckPayload) payload);

            case UNSUBSCRIBE:
                return new MqttUnsubscribeMessage(
                        mqttFixedHeader,
                        (MqttMessageIdVariableHeader) variableHeader,
                        (MqttUnsubscribePayload) payload);

            case PUBLISH:
                return new MqttPublishMessage(
                        mqttFixedHeader,
                        (MqttPublishVariableHeader) variableHeader,
                        (ByteBuf) payload);

            case PUBACK:
                //Having MqttPubReplyMessageVariableHeader or MqttMessageIdVariableHeader
                return new MqttPubAckMessage(mqttFixedHeader, (MqttMessageIdVariableHeader) variableHeader);
            case PUBREC:
            case PUBREL:
            case PUBCOMP:
                //Having MqttPubReplyMessageVariableHeader or MqttMessageIdVariableHeader
                return new MqttMessage(mqttFixedHeader, variableHeader);

            case PINGREQ:
            case PINGRESP:
                return new MqttMessage(mqttFixedHeader);

            case DISCONNECT:
            case AUTH:
                //Having MqttReasonCodeAndPropertiesVariableHeader
                return new MqttMessage(mqttFixedHeader,
                        variableHeader);

            default:
                throw new IllegalArgumentException("unknown message type: " + mqttFixedHeader.messageType());
        }
    }
@Test
    public void createUnsubscribeV5() {
        MqttFixedHeader fixedHeader = new MqttFixedHeader(MqttMessageType.UNSUBSCRIBE, false, AT_LEAST_ONCE, false, 0);

        MqttProperties properties = new MqttProperties();
        properties.add(new MqttProperties.UserProperty("correlationId", "111222"));
        MqttMessageIdAndPropertiesVariableHeader variableHeader =
                new MqttMessageIdAndPropertiesVariableHeader(SAMPLE_MESSAGE_ID, properties);

        List<String> topics = new ArrayList<String>();
        topics.add(SAMPLE_TOPIC);
        MqttUnsubscribePayload payload = new MqttUnsubscribePayload(topics);

        MqttMessage unsubscribe = MqttMessageFactory.newMessage(fixedHeader, variableHeader, payload);

        assertEquals(MqttMessageType.UNSUBSCRIBE, unsubscribe.fixedHeader().messageType());
        MqttMessageIdAndPropertiesVariableHeader actualVariableHeader =
                (MqttMessageIdAndPropertiesVariableHeader) unsubscribe.variableHeader();
        assertEquals(SAMPLE_MESSAGE_ID, actualVariableHeader.messageId());
        validateProperties(properties, actualVariableHeader.properties());
        MqttUnsubscribePayload actualPayload = (MqttUnsubscribePayload) unsubscribe.payload();
        validateUnsubscribePayload(payload, actualPayload);
    }