2

誰か助けてくれませんか。10 の私のスターターは、JMS とメッセージング全般についてほとんど (ほとんど何も) 知らないということです。

これは私にとっての学習演習であるため、非常に基本的な Spring JMS 構成をまとめ、それがどのように機能するかを理解するのに役立ついくつかの統合テストを作成しようとしています。

これは、JMS コンポーネントを含む現在の Spring コンテキスト構成です。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:jms="http://www.springframework.org/schema/jms"
       xmlns:amq="http://activemq.apache.org/schema/core"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans.xsd
                           http://www.springframework.org/schema/context
                           http://www.springframework.org/schema/context/spring-context.xsd
                           http://www.springframework.org/schema/jms
                           http://www.springframework.org/schema/jms/spring-jms.xsd
                           http://activemq.apache.org/schema/core
                           http://activemq.apache.org/schema/core/activemq-core.xsd">

    <bean class="com.lv.gi.jmstest.ApplicationContextProvider" />

    <!--  Embedded ActiveMQ Broker -->
    <amq:broker id="broker" useJmx="false" persistent="false">
        <amq:transportConnectors>
            <amq:transportConnector uri="tcp://localhost:0" />
        </amq:transportConnectors>
    </amq:broker>

    <!--  ActiveMQ Destination  -->
    <amq:queue id="destination" physicalName="myQueueName" />

    <!-- JMS ConnectionFactory to use, configuring the embedded broker using XML -->
    <amq:connectionFactory id="jmsFactory" brokerURL="vm://localhost" />

    <!-- JMS Producer Configuration -->
    <bean id="jmsProducerConnectionFactory"
          class="org.springframework.jms.connection.SingleConnectionFactory"
          depends-on="broker"
          p:targetConnectionFactory-ref="jmsFactory" />

    <bean id="jmsProducerTemplate" class="org.springframework.jms.core.JmsTemplate"
          p:connectionFactory-ref="jmsProducerConnectionFactory"
          p:defaultDestination-ref="destination" />

    <bean class="com.lv.gi.jmstest.JmsMessageProducer">
        <constructor-arg index="0" ref="jmsProducerTemplate" />
    </bean>

    <!-- JMS Consumer Configuration -->
    <bean id="jmsConsumerConnectionFactory"
          class="org.springframework.jms.connection.SingleConnectionFactory"
          depends-on="broker"
          p:targetConnectionFactory-ref="jmsFactory" />

    <jms:listener-container container-type="default"
                            connection-factory="jmsConsumerConnectionFactory"
                            acknowledge="auto">
        <jms:listener destination="myQueueName" ref="jmsMessageListener" />
    </jms:listener-container>

    <bean id="jmsMessageListener" class="com.lv.gi.jmstest.JmsMessageListener" />
</beans>

私の JmsMessageProducer クラスには、次のような postMessage メソッドがあります。

public void postMessage(final String message) {
    template.send(new MessageCreator() {
        @Override
        public Message createMessage(final Session session) throws JMSException {
            final TextMessage textMessage = session.createTextMessage(message);
            LOGGER.info("Sending message: " + message);

            return textMessage;
        }
    });
}

そして、私の JmsMessageListener (MessageListener を実装する) には、次のような onMessage メソッドがあります。

public void onMessage(final Message message) {
    try {
        if (message instanceof TextMessage) {
            final TextMessage tm = (TextMessage)message;
            final String msg = tm.getText();

            LOGGER.info("Received message '{}'", msg);
        }
    } catch (final JMSException e) {
        LOGGER.error(e.getMessage(), e);
    }
}

私のテスト クラスでは、Spring コンテキストを起動し、JmsMessageProducer Bean を取得して、postMessage を呼び出すことができます。コンソールに期待どおりのメッセージが表示されます。

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:/com/lv/gi/jmstest/JmsMessageListenerTest-context.xml" })
public class TestJms {

    private JmsMessageProducer jmsMessageProducer;

    @Before
    public void setup() {
        jmsMessageProducer = ApplicationContextProvider.getApplicationContext().getBean(JmsMessageProducer.class);
    }

    @Test
    public void doStuff() throws InterruptedException {
        jmsMessageProducer.postMessage("message 1");
    }
}

これは機能しますが、コンソールで受信したメッセージを視覚的に見る以外に、メッセージが受信されたと断言できないため、それほど多くのテストではありません。

私たちはmockitoを使用しているので、テスト内でMessageListener Beanをモックに置き換えてverifyを呼び出す方法があるかどうか疑問に思っています。これらのテストの目的で別の Spring コンテキスト ファイルを提供することでそれを行うことができると思いますが、次の要件ではうまく機能しない可能性があります...

これらすべての最終目標は、メッセージ プロデューサがメッセージをキューに送信できるトピックを作成することです。1 つ以上の MessageListeners がキューからメッセージを読み取り、すべての登録済みリスナーがメッセージを読み取ると、メッセージはキューから削除されます。(トピックはこれに適した用語だと思います!)

このシステムが機能することを証明するには、Spring コンテキストを起動できるテストが必要です。最初にやりたいことは、リスナーをすべて同じ宛先に接続された 3 つのモックに置き換えて、それぞれで検証を使用できるようにすることです。メッセージを投稿してから、各モックが受信されたことを確認します。次に、2 つのリスナーを削除/無効化し、postMessage を呼び出し、残りの 1 つのモック リスナーで onMessage メソッドが呼び出されたことを確認します。その後、しばらく待ってから、2 つのモックを再構築し、onMessage メソッドが呼び出されたことを確認します。最後に、メッセージがキューにないことを確認します (3 つの登録済みリスナーがすべてメッセージを受信したため)。

上記を念頭に置いて、私やろうとしているのは、実行時に宛先に対してリスナーを登録および登録解除(または無効化)することだと思います。それができれば、モックを登録できます。

ふぅ!、それは複雑です!しかし、私がやろうとしていることは理にかなっていると思いますか?

これを達成する方法についての指針はありますか?よろしくお願いします。

ネイサン

4

1 に答える 1