Package org.springframework.amqp.rabbit.core

Source Code of org.springframework.amqp.rabbit.core.RabbitTemplateTests

/*
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.springframework.amqp.rabbit.core;

import static org.hamcrest.Matchers.containsString;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;

import org.junit.Test;
import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;

import org.springframework.amqp.AmqpAuthenticationException;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageProperties;
import org.springframework.amqp.core.ReceiveAndReplyCallback;
import org.springframework.amqp.rabbit.connection.AbstractRoutingConnectionFactory;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.connection.SimpleRoutingConnectionFactory;
import org.springframework.amqp.rabbit.connection.SingleConnectionFactory;
import org.springframework.amqp.support.converter.SimpleMessageConverter;
import org.springframework.amqp.utils.SerializationUtils;
import org.springframework.expression.Expression;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.retry.RecoveryCallback;
import org.springframework.retry.RetryContext;
import org.springframework.retry.support.RetryTemplate;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionException;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.AbstractPlatformTransactionManager;
import org.springframework.transaction.support.DefaultTransactionStatus;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionTemplate;

import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.AuthenticationFailureException;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.Consumer;
import com.rabbitmq.client.Envelope;
import com.rabbitmq.client.impl.AMQImpl;

/**
* @author Gary Russell
* @author Artem Bilan
* @since 1.0.1
*
*/
public class RabbitTemplateTests {

  @Test
  public void returnConnectionAfterCommit() throws Exception {
    @SuppressWarnings("serial")
    TransactionTemplate txTemplate = new TransactionTemplate(new AbstractPlatformTransactionManager() {

      @Override
      protected Object doGetTransaction() throws TransactionException {
        return new Object();
      }

      @Override
      protected void doBegin(Object transaction, TransactionDefinition definition) throws TransactionException {
      }

      @Override
      protected void doCommit(DefaultTransactionStatus status) throws TransactionException {
      }

      @Override
      protected void doRollback(DefaultTransactionStatus status) throws TransactionException {
      }
    });
    ConnectionFactory mockConnectionFactory = mock(ConnectionFactory.class);
    Connection mockConnection = mock(Connection.class);
    Channel mockChannel = mock(Channel.class);

    when(mockConnectionFactory.newConnection((ExecutorService) null)).thenReturn(mockConnection);
    when(mockConnection.isOpen()).thenReturn(true);
    when(mockConnection.createChannel()).thenReturn(mockChannel);

    when(mockChannel.isOpen()).thenReturn(true);

    final RabbitTemplate template = new RabbitTemplate(new CachingConnectionFactory(mockConnectionFactory));
    template.setChannelTransacted(true);

    txTemplate.execute(new TransactionCallback<Object>() {
      @Override
      public Object doInTransaction(TransactionStatus status) {
        template.convertAndSend("foo", "bar");
        return null;
      }
    });
    txTemplate.execute(new TransactionCallback<Object>() {
      @Override
      public Object doInTransaction(TransactionStatus status) {
        template.convertAndSend("baz", "qux");
        return null;
      }
    });
    verify(mockConnectionFactory, Mockito.times(1)).newConnection(Mockito.any(ExecutorService.class));
    // ensure we used the same channel
    verify(mockConnection, Mockito.times(1)).createChannel();
  }

  @Test
  public void testConvertBytes() {
    RabbitTemplate template = new RabbitTemplate();
    byte[] payload = "Hello, world!".getBytes();
    Message message = template.convertMessageIfNecessary(payload);
    assertSame(payload, message.getBody());
  }

  @Test
  public void testConvertString() throws Exception {
    RabbitTemplate template = new RabbitTemplate();
    String payload = "Hello, world!";
    Message message = template.convertMessageIfNecessary(payload);
    assertEquals(payload, new String(message.getBody(), SimpleMessageConverter.DEFAULT_CHARSET));
  }

  @Test
  public void testConvertSerializable() throws Exception {
    RabbitTemplate template = new RabbitTemplate();
    Long payload = 43L;
    Message message = template.convertMessageIfNecessary(payload);
    assertEquals(payload, SerializationUtils.deserialize(message.getBody()));
  }

  @Test
  public void testConvertMessage() throws Exception {
    RabbitTemplate template = new RabbitTemplate();
    Message input = new Message("Hello, world!".getBytes(), new MessageProperties());
    Message message = template.convertMessageIfNecessary(input);
    assertSame(input, message);
  }

  @SuppressWarnings("unchecked")
  @Test // AMQP-249
  public void dontHangConsumerThread() throws Exception {
    ConnectionFactory mockConnectionFactory = mock(ConnectionFactory.class);
    Connection mockConnection = mock(Connection.class);
    Channel mockChannel = mock(Channel.class);

    when(mockConnectionFactory.newConnection((ExecutorService) null)).thenReturn(mockConnection);
    when(mockConnection.isOpen()).thenReturn(true);
    when(mockConnection.createChannel()).thenReturn(mockChannel);

    when(mockChannel.queueDeclare()).thenReturn(new AMQImpl.Queue.DeclareOk("foo", 0, 0));

    final AtomicReference<Consumer> consumer = new AtomicReference<Consumer>();
    doAnswer(new Answer<Object>() {
      @Override
      public Object answer(InvocationOnMock invocation) throws Throwable {
        consumer.set((Consumer) invocation.getArguments()[6]);
        return null;
      }
    }).when(mockChannel).basicConsume(Mockito.anyString(), Mockito.anyBoolean(), Mockito.anyString(),
        Mockito.anyBoolean(), Mockito.anyBoolean(), Mockito.anyMap(), Mockito.any(Consumer.class));
    RabbitTemplate template = new RabbitTemplate(new SingleConnectionFactory(mockConnectionFactory));
    template.setReplyTimeout(1);
    Message input = new Message("Hello, world!".getBytes(), new MessageProperties());
    template.doSendAndReceiveWithTemporary("foo", "bar", input);
    Envelope envelope = new Envelope(1, false, "foo", "bar");
    // used to hang here because of the SynchronousQueue and doSendAndReceive() already exited
    consumer.get().handleDelivery("foo", envelope, new AMQP.BasicProperties(), new byte[0]);
  }

  @Test
  public void testRetry() throws Exception {
    ConnectionFactory mockConnectionFactory = mock(ConnectionFactory.class);
    final AtomicInteger count = new AtomicInteger();
    doAnswer(new Answer<Void>() {

      @Override
      public Void answer(InvocationOnMock invocation) throws Throwable {
        count.incrementAndGet();
        throw new AuthenticationFailureException("foo");
      }
    }).when(mockConnectionFactory).newConnection((ExecutorService) null);

    RabbitTemplate template = new RabbitTemplate(new SingleConnectionFactory(mockConnectionFactory));
    template.setRetryTemplate(new RetryTemplate());
    try {
      template.convertAndSend("foo", "bar", "baz");
    }
    catch (AmqpAuthenticationException e) {
      assertThat(e.getMessage(), containsString("foo"));
    }
    assertEquals(3, count.get());
  }

  @Test
  public void testRecovery() throws Exception {
    ConnectionFactory mockConnectionFactory = mock(ConnectionFactory.class);
    final AtomicInteger count = new AtomicInteger();
    doAnswer(new Answer<Void>() {

      @Override
      public Void answer(InvocationOnMock invocation) throws Throwable {
        count.incrementAndGet();
        throw new AuthenticationFailureException("foo");
      }
    }).when(mockConnectionFactory).newConnection((ExecutorService) null);

    RabbitTemplate template = new RabbitTemplate(new SingleConnectionFactory(mockConnectionFactory));
    template.setRetryTemplate(new RetryTemplate());

    final AtomicBoolean recoverInvoked = new AtomicBoolean();

    template.setRecoveryCallback(new RecoveryCallback<Object>() {

      @Override
      public Object recover(RetryContext context) throws Exception {
        recoverInvoked.set(true);
        return null;
      }

    });
    template.convertAndSend("foo", "bar", "baz");
    assertEquals(3, count.get());
    assertTrue(recoverInvoked.get());
  }

  public final static AtomicInteger LOOKUP_KEY_COUNT = new AtomicInteger();

  @Test
  @SuppressWarnings("unchecked")
  public void testRoutingConnectionFactory() throws Exception {
    org.springframework.amqp.rabbit.connection.ConnectionFactory connectionFactory1 =
        Mockito.mock(org.springframework.amqp.rabbit.connection.ConnectionFactory.class);
    org.springframework.amqp.rabbit.connection.ConnectionFactory connectionFactory2 =
        Mockito.mock(org.springframework.amqp.rabbit.connection.ConnectionFactory.class);
    Map<Object, org.springframework.amqp.rabbit.connection.ConnectionFactory> factories =
        new HashMap<Object, org.springframework.amqp.rabbit.connection.ConnectionFactory>(2);
    factories.put("foo", connectionFactory1);
    factories.put("bar", connectionFactory2);


    AbstractRoutingConnectionFactory connectionFactory = new SimpleRoutingConnectionFactory();
    connectionFactory.setTargetConnectionFactories(factories);

    final RabbitTemplate template = new RabbitTemplate(connectionFactory);
    Expression expression = new SpelExpressionParser()
        .parseExpression("T(org.springframework.amqp.rabbit.core.RabbitTemplateTests)" +
            ".LOOKUP_KEY_COUNT.getAndIncrement() % 2 == 0 ? 'foo' : 'bar'");
    template.setSendConnectionFactorySelectorExpression(expression);
    template.setReceiveConnectionFactorySelectorExpression(expression);

    for (int i = 0; i < 3; i++) {
      try {
        template.convertAndSend("foo", "bar", "baz");
      }
      catch (Exception e) {
        //Ignore it. Doesn't matter for this test.
      }
      try {
        template.receive("foo");
      }
      catch (Exception e) {
        //Ignore it. Doesn't matter for this test.
      }
      try {
        template.receiveAndReply("foo", mock(ReceiveAndReplyCallback.class));
      }
      catch (Exception e) {
        //Ignore it. Doesn't matter for this test.
      }
    }

    Mockito.verify(connectionFactory1, Mockito.times(5)).createConnection();
    Mockito.verify(connectionFactory2, Mockito.times(4)).createConnection();
  }

}
TOP

Related Classes of org.springframework.amqp.rabbit.core.RabbitTemplateTests

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.