使用Spring,JMS和ActiveMQ进行消费者驱动的合同测试

时间:2019-07-24 13:35:15

标签: activemq spring-cloud spring-jms producer-consumer spring-cloud-contract

我目前正在尝试在使用ActiveMQ消息进行通信的服务的上下文中学习由消费者驱动的合同测试。 Spring提供了有关Spring Cloud Contract Verifier消息传递的文档 https://cloud.spring.io/spring-cloud-contract/spring-cloud-contract.html#_spring_cloud_contract_verifier_messaging 但是我无法按照我已有的设置(Spring Services和ActiveMQ)进行设置。

我的问题是:

  • 使用消费者驱动的合同测试进行消息传递是个好主意吗?
  • 最佳做法是什么?
  • 如果这是个好主意,那么您是否有任何有关通过JMS和ActiveMQ进行通信的消费者驱动的合同测试春季服务的良好教程?

2 个答案:

答案 0 :(得分:1)

我设法为JMS和ActiveMQ创建了一个自定义MessageVerifier,如下所示:

package de.itemis.seatreservationservice;

import com.fasterxml.jackson.databind.ObjectMapper;
import de.itemis.seatreservationservice.domain.ReservationRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.contract.verifier.messaging.MessageVerifier;
import org.springframework.context.annotation.Primary;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.messaging.support.GenericMessage;
import org.springframework.stereotype.Component;

import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.TextMessage;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Component
@Primary
public class JmsMessageVerifier implements MessageVerifier {

    @Autowired
    JmsTemplate jmsTemplate;

    @Autowired
    ObjectMapper mapper;

    @Override
    public void send(Object message, String destination) {
        jmsTemplate.convertAndSend(destination, message, new ReplyToProcessor());
    }

    @Override
    public Object receive(String destination, long timeout, TimeUnit timeUnit) {
        jmsTemplate.setReceiveTimeout(timeout);
        return receiveMessage(destination);
    }

    @Override
    public Object receive(String destination) {
        return receiveMessage(destination);
    }

    @Override
    public void send(Object payload, Map headers, String destination) {
        ReservationRequest request = null;
        try {
            request = mapper.readValue((String) payload, ReservationRequest.class);
        } catch (IOException e) {
            e.printStackTrace();
        }
        jmsTemplate.convertAndSend(destination, request, new ReplyToProcessor());
    }



    private Object receiveMessage(String queueName) {
        Message message = jmsTemplate.receive(queueName);
        TextMessage textMessage = (TextMessage) message;
        try {
            return new GenericMessage<>(textMessage.getText());
        } catch (JMSException e) {
            e.printStackTrace();
            return null;
        }
    }
}

当前,我在两个测试文件夹(生产者和消费者)中都需要它们。 通常,我希望我的Producer中的JmsMessageVerifier会打包在生成的存根JAR中,以便消费者合同测试使用此JmsMessageVerifier而不是自己实现。

您对此Marcin Grzejszczak有何看法?

如果该功能有用,我会为此创建一个Issue。

这是同时提供两项服务的repository

答案 1 :(得分:0)

  

但是我无法按照我的设置(Spring Services和ActiveMQ)进行操作。

不支持现成的ActiveMQ,您必须提供自己的MessageVerifier类型的bean,在那里您将教该框架如何发送和接收消息

  

使用消费者驱动的合同测试进行消息传递是个好主意吗?

绝对!您可以遵循与HTTP相同的流程,但是要进行消息传递

  

最佳做法是什么?

这取决于;)您可以遵循执行cdc的标准做法,就好像它是基于http的通信一样。如果您要以某种方式抽象此类消息的产生者和使用者,从而更加关注主题/队列,则可以遵循此指南https://cloud.spring.io/spring-cloud-static/Greenwich.SR2/single/spring-cloud.html#_how_can_i_define_messaging_contracts_per_topic_not_per_producer,在此我们描述如何根据每个主题定义消息传递合同,不是每个生产者

  

如果这是个好主意,那么您是否有任何有关通过JMS和ActiveMQ进行通信的消费者驱动的合同测试spring服务的良好教程?

正如我之前所说,我们没有开箱即用的支持。但是,您可以使用Spring Integration或Apache Camel并通过这些与ActiveMQ进行通信。