/*
* Copyright 2013-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.cloud.aws.messaging.core;
import com.amazonaws.AmazonServiceException;
import com.amazonaws.services.sqs.AmazonSQSAsync;
import com.amazonaws.services.sqs.model.MessageAttributeValue;
import com.amazonaws.services.sqs.model.ReceiveMessageRequest;
import com.amazonaws.services.sqs.model.ReceiveMessageResult;
import com.amazonaws.services.sqs.model.SendMessageRequest;
import com.amazonaws.services.sqs.model.SendMessageResult;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.mockito.ArgumentCaptor;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.MessageDeliveryException;
import org.springframework.messaging.MessageHeaders;
import org.springframework.messaging.MessagingException;
import org.springframework.messaging.PollableChannel;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.util.MimeType;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicInteger;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyMapOf;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.only;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
/**
* @author Agim Emruli
* @author Alain Sahli
* @since 1.0
*/
public class QueueMessageChannelTest {
@Rule
public ExpectedException expectedException = ExpectedException.none();
@Test
public void sendMessage_validTextMessage_returnsTrue() throws Exception {
// Arrange
AmazonSQSAsync amazonSqs = mock(AmazonSQSAsync.class);
ArgumentCaptor<SendMessageRequest> sendMessageRequestArgumentCaptor = ArgumentCaptor.forClass(SendMessageRequest.class);
when(amazonSqs.sendMessage(sendMessageRequestArgumentCaptor.capture())).thenReturn(new SendMessageResult());
Message<String> stringMessage = MessageBuilder.withPayload("message content").build();
MessageChannel messageChannel = new QueueMessageChannel(amazonSqs, "http://testQueue");
// Act
boolean sent = messageChannel.send(stringMessage);
// Assert
verify(amazonSqs, only()).sendMessage(any(SendMessageRequest.class));
assertEquals("message content", sendMessageRequestArgumentCaptor.getValue().getMessageBody());
assertTrue(sent);
}
@Test
public void sendMessage_serviceThrowsError_throwsMessagingException() throws Exception {
//Arrange
AmazonSQSAsync amazonSqs = mock(AmazonSQSAsync.class);
Message<String> stringMessage = MessageBuilder.withPayload("message content").build();
MessageChannel messageChannel = new QueueMessageChannel(amazonSqs, "http://testQueue");
when(amazonSqs.sendMessage(new SendMessageRequest("http://testQueue", "message content").withDelaySeconds(0)
.withMessageAttributes(anyMapOf(String.class, MessageAttributeValue.class)))).
thenThrow(new AmazonServiceException("wanted error"));
//Assert
this.expectedException.expect(MessagingException.class);
this.expectedException.expectMessage("wanted error");
//Act
messageChannel.send(stringMessage);
}
@Test
public void sendMessage_withMimeTypeAsStringHeader_shouldPassItAsMessageAttribute() throws Exception {
// Arrange
AmazonSQSAsync amazonSqs = mock(AmazonSQSAsync.class);
QueueMessageChannel messageChannel = new QueueMessageChannel(amazonSqs, "http://testQueue");
String mimeTypeAsString = new MimeType("test", "plain", Charset.forName("UTF-8")).toString();
Message<String> message = MessageBuilder.withPayload("Hello").setHeader(MessageHeaders.CONTENT_TYPE, mimeTypeAsString).build();
ArgumentCaptor<SendMessageRequest> sendMessageRequestArgumentCaptor = ArgumentCaptor.forClass(SendMessageRequest.class);
when(amazonSqs.sendMessage(sendMessageRequestArgumentCaptor.capture())).thenReturn(new SendMessageResult());
// Act
boolean sent = messageChannel.send(message);
// Assert
assertTrue(sent);
assertEquals(mimeTypeAsString, sendMessageRequestArgumentCaptor.getValue().getMessageAttributes().get(MessageHeaders.CONTENT_TYPE).getStringValue());
}
@Test
public void sendMessage_withMimeTypeHeader_shouldPassItAsMessageAttribute() throws Exception {
// Arrange
AmazonSQSAsync amazonSqs = mock(AmazonSQSAsync.class);
QueueMessageChannel messageChannel = new QueueMessageChannel(amazonSqs, "http://testQueue");
MimeType mimeType = new MimeType("test", "plain", Charset.forName("UTF-8"));
Message<String> message = MessageBuilder.withPayload("Hello").setHeader(MessageHeaders.CONTENT_TYPE, mimeType).build();
ArgumentCaptor<SendMessageRequest> sendMessageRequestArgumentCaptor = ArgumentCaptor.forClass(SendMessageRequest.class);
when(amazonSqs.sendMessage(sendMessageRequestArgumentCaptor.capture())).thenReturn(new SendMessageResult());
// Act
boolean sent = messageChannel.send(message);
// Assert
assertTrue(sent);
assertEquals(mimeType.toString(), sendMessageRequestArgumentCaptor.getValue().getMessageAttributes().get(MessageHeaders.CONTENT_TYPE).getStringValue());
}
@Test
public void receiveMessage_withoutTimeout_returnsTextMessage() throws Exception {
// Arrange
AmazonSQSAsync amazonSqs = mock(AmazonSQSAsync.class);
when(amazonSqs.receiveMessage(new ReceiveMessageRequest("http://testQueue").
withWaitTimeSeconds(0).
withMaxNumberOfMessages(1).
withAttributeNames(QueueMessageChannel.ATTRIBUTE_NAMES).
withMessageAttributeNames("All"))).
thenReturn(new ReceiveMessageResult().withMessages(
Collections.singleton(new com.amazonaws.services.sqs.model.Message().withBody("content"))));
PollableChannel messageChannel = new QueueMessageChannel(amazonSqs, "http://testQueue");
//Act
Message<?> receivedMessage = messageChannel.receive();
//Assert
assertNotNull(receivedMessage);
assertEquals("content", receivedMessage.getPayload());
}
@Test
public void receiveMessage_withSpecifiedTimeout_returnsTextMessage() throws Exception {
// Arrange
AmazonSQSAsync amazonSqs = mock(AmazonSQSAsync.class);
when(amazonSqs.receiveMessage(new ReceiveMessageRequest("http://testQueue").
withWaitTimeSeconds(2).
withMaxNumberOfMessages(1).
withAttributeNames(QueueMessageChannel.ATTRIBUTE_NAMES).
withMessageAttributeNames("All"))).
thenReturn(new ReceiveMessageResult().withMessages(
Collections.singleton(new com.amazonaws.services.sqs.model.Message().withBody("content"))));
PollableChannel messageChannel = new QueueMessageChannel(amazonSqs, "http://testQueue");
//Act
Message<?> receivedMessage = messageChannel.receive(2);
//Assert
assertNotNull(receivedMessage);
assertEquals("content", receivedMessage.getPayload());
}
@Test
public void receiveMessage_withSpecifiedTimeout_returnsNull() throws Exception {
// Arrange
AmazonSQSAsync amazonSqs = mock(AmazonSQSAsync.class);
when(amazonSqs.receiveMessage(new ReceiveMessageRequest("http://testQueue").
withWaitTimeSeconds(2).
withMaxNumberOfMessages(1).
withAttributeNames(QueueMessageChannel.ATTRIBUTE_NAMES).
withMessageAttributeNames("All"))).
thenReturn(new ReceiveMessageResult().withMessages(
Collections.<com.amazonaws.services.sqs.model.Message>emptyList()));
PollableChannel messageChannel = new QueueMessageChannel(amazonSqs, "http://testQueue");
//Act
Message<?> receivedMessage = messageChannel.receive(2);
//Assert
assertNull(receivedMessage);
}
@Test
public void receiveMessage_withoutDefaultTimeout_returnsNull() throws Exception {
// Arrange
AmazonSQSAsync amazonSqs = mock(AmazonSQSAsync.class);
when(amazonSqs.receiveMessage(new ReceiveMessageRequest("http://testQueue").
withWaitTimeSeconds(0).
withMaxNumberOfMessages(1).
withAttributeNames(QueueMessageChannel.ATTRIBUTE_NAMES).
withMessageAttributeNames("All"))).
thenReturn(new ReceiveMessageResult().withMessages(
Collections.<com.amazonaws.services.sqs.model.Message>emptyList()));
PollableChannel messageChannel = new QueueMessageChannel(amazonSqs, "http://testQueue");
//Act
Message<?> receivedMessage = messageChannel.receive(0);
//Assert
assertNull(receivedMessage);
}
@Test
public void receiveMessage_withMimeTypeMessageAttribute_shouldCopyToHeaders() throws Exception {
// Arrange
AmazonSQSAsync amazonSqs = mock(AmazonSQSAsync.class);
MimeType mimeType = new MimeType("test", "plain", Charset.forName("UTF-8"));
when(amazonSqs.receiveMessage(new ReceiveMessageRequest("http://testQueue").
withWaitTimeSeconds(0).
withMaxNumberOfMessages(1).
withAttributeNames(QueueMessageChannel.ATTRIBUTE_NAMES).
withMessageAttributeNames("All"))).
thenReturn(new ReceiveMessageResult().withMessages(new com.amazonaws.services.sqs.model.Message().withBody("Hello").
withMessageAttributes(Collections.singletonMap(MessageHeaders.CONTENT_TYPE,
new MessageAttributeValue().withDataType(MessageAttributeDataTypes.STRING).withStringValue(mimeType.toString())))));
PollableChannel messageChannel = new QueueMessageChannel(amazonSqs, "http://testQueue");
// Act
Message<?> receivedMessage = messageChannel.receive();
// Assert
assertEquals(mimeType, receivedMessage.getHeaders().get(MessageHeaders.CONTENT_TYPE));
}
@Test
public void sendMessage_withStringMessageHeader_shouldBeSentAsQueueMessageAttribute() throws Exception {
// Arrange
AmazonSQSAsync amazonSqs = mock(AmazonSQSAsync.class);
QueueMessageChannel messageChannel = new QueueMessageChannel(amazonSqs, "http://testQueue");
String headerValue = "Header value";
String headerName = "MyHeader";
Message<String> message = MessageBuilder.withPayload("Hello").setHeader(headerName, headerValue).build();
ArgumentCaptor<SendMessageRequest> sendMessageRequestArgumentCaptor = ArgumentCaptor.forClass(SendMessageRequest.class);
when(amazonSqs.sendMessage(sendMessageRequestArgumentCaptor.capture())).thenReturn(new SendMessageResult());
// Act
boolean sent = messageChannel.send(message);
// Assert
assertTrue(sent);
assertEquals(headerValue, sendMessageRequestArgumentCaptor.getValue().getMessageAttributes().get(headerName).getStringValue());
assertEquals(MessageAttributeDataTypes.STRING, sendMessageRequestArgumentCaptor.getValue().getMessageAttributes().get(headerName).getDataType());
}
@Test
public void receiveMessage_withStringMessageHeader_shouldBeReceivedAsQueueMessageAttribute() throws Exception {
// Arrange
AmazonSQSAsync amazonSqs = mock(AmazonSQSAsync.class);
String headerValue = "Header value";
String headerName = "MyHeader";
when(amazonSqs.receiveMessage(new ReceiveMessageRequest("http://testQueue").
withWaitTimeSeconds(0).
withMaxNumberOfMessages(1).
withAttributeNames(QueueMessageChannel.ATTRIBUTE_NAMES).
withMessageAttributeNames("All"))).
thenReturn(new ReceiveMessageResult().withMessages(new com.amazonaws.services.sqs.model.Message().withBody("Hello").
withMessageAttributes(Collections.singletonMap(headerName,
new MessageAttributeValue().withDataType(MessageAttributeDataTypes.STRING).withStringValue(headerValue)))));
PollableChannel messageChannel = new QueueMessageChannel(amazonSqs, "http://testQueue");
// Act
Message<?> receivedMessage = messageChannel.receive();
// Assert
assertEquals(headerValue, receivedMessage.getHeaders().get(headerName));
}
@Test
public void sendMessage_withNumericMessageHeaders_shouldBeSentAsQueueMessageAttributes() throws Exception {
// Arrange
AmazonSQSAsync amazonSqs = mock(AmazonSQSAsync.class);
QueueMessageChannel messageChannel = new QueueMessageChannel(amazonSqs, "http://testQueue");
double doubleValue = 1234.56;
long longValue = 1234L;
int integerValue = 1234;
byte byteValue = 2;
short shortValue = 12;
float floatValue = 1234.56f;
BigInteger bigIntegerValue = new BigInteger("616416546156");
BigDecimal bigDecimalValue = new BigDecimal("7834938");
Message<String> message = MessageBuilder.withPayload("Hello")
.setHeader("double", doubleValue)
.setHeader("long", longValue)
.setHeader("integer", integerValue)
.setHeader("byte", byteValue)
.setHeader("short", shortValue)
.setHeader("float", floatValue)
.setHeader("bigInteger", bigIntegerValue)
.setHeader("bigDecimal", bigDecimalValue)
.build();
ArgumentCaptor<SendMessageRequest> sendMessageRequestArgumentCaptor = ArgumentCaptor.forClass(SendMessageRequest.class);
when(amazonSqs.sendMessage(sendMessageRequestArgumentCaptor.capture())).thenReturn(new SendMessageResult());
// Act
boolean sent = messageChannel.send(message);
// Assert
assertTrue(sent);
Map<String, MessageAttributeValue> messageAttributes = sendMessageRequestArgumentCaptor.getValue().getMessageAttributes();
assertEquals(MessageAttributeDataTypes.NUMBER + ".java.lang.Double", messageAttributes.get("double").getDataType());
assertEquals(String.valueOf(doubleValue), messageAttributes.get("double").getStringValue());
assertEquals(MessageAttributeDataTypes.NUMBER + ".java.lang.Long", messageAttributes.get("long").getDataType());
assertEquals(String.valueOf(longValue), messageAttributes.get("long").getStringValue());
assertEquals(MessageAttributeDataTypes.NUMBER + ".java.lang.Integer", messageAttributes.get("integer").getDataType());
assertEquals(String.valueOf(integerValue), messageAttributes.get("integer").getStringValue());
assertEquals(MessageAttributeDataTypes.NUMBER + ".java.lang.Byte", messageAttributes.get("byte").getDataType());
assertEquals(String.valueOf(byteValue), messageAttributes.get("byte").getStringValue());
assertEquals(MessageAttributeDataTypes.NUMBER + ".java.lang.Short", messageAttributes.get("short").getDataType());
assertEquals(String.valueOf(shortValue), messageAttributes.get("short").getStringValue());
assertEquals(MessageAttributeDataTypes.NUMBER + ".java.lang.Float", messageAttributes.get("float").getDataType());
assertEquals(String.valueOf(floatValue), messageAttributes.get("float").getStringValue());
assertEquals(MessageAttributeDataTypes.NUMBER + ".java.math.BigInteger", messageAttributes.get("bigInteger").getDataType());
assertEquals(String.valueOf(bigIntegerValue), messageAttributes.get("bigInteger").getStringValue());
assertEquals(MessageAttributeDataTypes.NUMBER + ".java.math.BigDecimal", messageAttributes.get("bigDecimal").getDataType());
assertEquals(String.valueOf(bigDecimalValue), messageAttributes.get("bigDecimal").getStringValue());
}
@Test
public void receiveMessage_withNumericMessageHeaders_shouldBeReceivedAsQueueMessageAttributes() throws Exception {
// Arrange
AmazonSQSAsync amazonSqs = mock(AmazonSQSAsync.class);
HashMap<String, MessageAttributeValue> messageAttributes = new HashMap<>();
double doubleValue = 1234.56;
messageAttributes.put("double", new MessageAttributeValue().withDataType(MessageAttributeDataTypes.NUMBER + ".java.lang.Double").withStringValue(String.valueOf(doubleValue)));
long longValue = 1234L;
messageAttributes.put("long", new MessageAttributeValue().withDataType(MessageAttributeDataTypes.NUMBER + ".java.lang.Long").withStringValue(String.valueOf(longValue)));
int integerValue = 1234;
messageAttributes.put("integer", new MessageAttributeValue().withDataType(MessageAttributeDataTypes.NUMBER + ".java.lang.Integer").withStringValue(String.valueOf(integerValue)));
byte byteValue = 2;
messageAttributes.put("byte", new MessageAttributeValue().withDataType(MessageAttributeDataTypes.NUMBER + ".java.lang.Byte").withStringValue(String.valueOf(byteValue)));
short shortValue = 12;
messageAttributes.put("short", new MessageAttributeValue().withDataType(MessageAttributeDataTypes.NUMBER + ".java.lang.Short").withStringValue(String.valueOf(shortValue)));
float floatValue = 1234.56f;
messageAttributes.put("float", new MessageAttributeValue().withDataType(MessageAttributeDataTypes.NUMBER + ".java.lang.Float").withStringValue(String.valueOf(floatValue)));
BigInteger bigIntegerValue = new BigInteger("616416546156");
messageAttributes.put("bigInteger", new MessageAttributeValue().withDataType(MessageAttributeDataTypes.NUMBER + ".java.math.BigInteger").withStringValue(String.valueOf(bigIntegerValue)));
BigDecimal bigDecimalValue = new BigDecimal("7834938");
messageAttributes.put("bigDecimal", new MessageAttributeValue().withDataType(MessageAttributeDataTypes.NUMBER + ".java.math.BigDecimal").withStringValue(String.valueOf(bigDecimalValue)));
when(amazonSqs.receiveMessage(new ReceiveMessageRequest("http://testQueue").
withWaitTimeSeconds(0).
withMaxNumberOfMessages(1).
withAttributeNames(QueueMessageChannel.ATTRIBUTE_NAMES).
withMessageAttributeNames("All"))).
thenReturn(new ReceiveMessageResult().withMessages(new com.amazonaws.services.sqs.model.Message().withBody("Hello").
withMessageAttributes(messageAttributes)));
PollableChannel messageChannel = new QueueMessageChannel(amazonSqs, "http://testQueue");
// Act
Message<?> receivedMessage = messageChannel.receive();
// Assert
assertEquals(doubleValue, receivedMessage.getHeaders().get("double"));
assertEquals(longValue, receivedMessage.getHeaders().get("long"));
assertEquals(integerValue, receivedMessage.getHeaders().get("integer"));
assertEquals(byteValue, receivedMessage.getHeaders().get("byte"));
assertEquals(shortValue, receivedMessage.getHeaders().get("short"));
assertEquals(floatValue, receivedMessage.getHeaders().get("float"));
assertEquals(bigIntegerValue, receivedMessage.getHeaders().get("bigInteger"));
assertEquals(bigDecimalValue, receivedMessage.getHeaders().get("bigDecimal"));
}
@Test
public void receiveMessage_withIncompatibleNumericMessageHeader_shouldThrowAnException() throws Exception {
// Arrange
AmazonSQSAsync amazonSqs = mock(AmazonSQSAsync.class);
this.expectedException.expect(IllegalArgumentException.class);
this.expectedException.expectMessage("Cannot convert String [17] to target class [java.util.concurrent.atomic.AtomicInteger]");
HashMap<String, MessageAttributeValue> messageAttributes = new HashMap<>();
AtomicInteger atomicInteger = new AtomicInteger(17);
messageAttributes.put("atomicInteger", new MessageAttributeValue().withDataType(MessageAttributeDataTypes.NUMBER + ".java.util.concurrent.atomic.AtomicInteger").withStringValue(String.valueOf(atomicInteger)));
when(amazonSqs.receiveMessage(new ReceiveMessageRequest("http://testQueue").
withWaitTimeSeconds(0).
withMaxNumberOfMessages(1).
withAttributeNames(QueueMessageChannel.ATTRIBUTE_NAMES).
withMessageAttributeNames("All"))).
thenReturn(new ReceiveMessageResult().withMessages(new com.amazonaws.services.sqs.model.Message().withBody("Hello").
withMessageAttributes(messageAttributes)));
PollableChannel messageChannel = new QueueMessageChannel(amazonSqs, "http://testQueue");
// Act
messageChannel.receive();
}
@Test
public void receiveMessage_withMissingNumericMessageHeaderTargetClass_shouldThrowAnException() throws Exception {
// Arrange
AmazonSQSAsync amazonSqs = mock(AmazonSQSAsync.class);
this.expectedException.expect(MessagingException.class);
this.expectedException.expectMessage("Message attribute with value '12' and data type 'Number.class.not.Found' could not be converted" +
" into a Number because target class was not found.");
HashMap<String, MessageAttributeValue> messageAttributes = new HashMap<>();
messageAttributes.put("classNotFound", new MessageAttributeValue().withDataType(MessageAttributeDataTypes.NUMBER + ".class.not.Found").withStringValue("12"));
when(amazonSqs.receiveMessage(new ReceiveMessageRequest("http://testQueue").
withWaitTimeSeconds(0).
withMaxNumberOfMessages(1).
withAttributeNames(QueueMessageChannel.ATTRIBUTE_NAMES).
withMessageAttributeNames("All"))).
thenReturn(new ReceiveMessageResult().withMessages(new com.amazonaws.services.sqs.model.Message().withBody("Hello").
withMessageAttributes(messageAttributes)));
PollableChannel messageChannel = new QueueMessageChannel(amazonSqs, "http://testQueue");
// Act
messageChannel.receive();
}
@Test
public void sendMessage_withBinaryMessageHeader_shouldBeSentAsBinaryMessageAttribute() throws Exception {
// Arrange
AmazonSQSAsync amazonSqs = mock(AmazonSQSAsync.class);
QueueMessageChannel messageChannel = new QueueMessageChannel(amazonSqs, "http://testQueue");
ByteBuffer headerValue = ByteBuffer.wrap("My binary data!".getBytes());
String headerName = "MyHeader";
Message<String> message = MessageBuilder.withPayload("Hello").setHeader(headerName, headerValue).build();
ArgumentCaptor<SendMessageRequest> sendMessageRequestArgumentCaptor = ArgumentCaptor.forClass(SendMessageRequest.class);
when(amazonSqs.sendMessage(sendMessageRequestArgumentCaptor.capture())).thenReturn(new SendMessageResult());
// Act
boolean sent = messageChannel.send(message);
// Assert
assertTrue(sent);
assertEquals(headerValue, sendMessageRequestArgumentCaptor.getValue().getMessageAttributes().get(headerName).getBinaryValue());
assertEquals(MessageAttributeDataTypes.BINARY, sendMessageRequestArgumentCaptor.getValue().getMessageAttributes().get(headerName).getDataType());
}
@Test
public void receiveMessage_withBinaryMessageHeader_shouldBeReceivedAsByteBufferMessageAttribute() throws Exception {
// Arrange
AmazonSQSAsync amazonSqs = mock(AmazonSQSAsync.class);
ByteBuffer headerValue = ByteBuffer.wrap("My binary data!".getBytes());
String headerName = "MyHeader";
when(amazonSqs.receiveMessage(new ReceiveMessageRequest("http://testQueue").
withWaitTimeSeconds(0).
withMaxNumberOfMessages(1).
withAttributeNames(QueueMessageChannel.ATTRIBUTE_NAMES).
withMessageAttributeNames("All"))).
thenReturn(new ReceiveMessageResult().withMessages(new com.amazonaws.services.sqs.model.Message().withBody("Hello").
withMessageAttributes(Collections.singletonMap(headerName,
new MessageAttributeValue().withDataType(MessageAttributeDataTypes.BINARY).withBinaryValue(headerValue)))));
PollableChannel messageChannel = new QueueMessageChannel(amazonSqs, "http://testQueue");
// Act
Message<?> receivedMessage = messageChannel.receive();
// Assert
assertEquals(headerValue, receivedMessage.getHeaders().get(headerName));
}
@Test
public void sendMessage_withUuidAsId_shouldConvertUuidToString() throws Exception {
// Arrange
AmazonSQSAsync amazonSqs = mock(AmazonSQSAsync.class);
QueueMessageChannel messageChannel = new QueueMessageChannel(amazonSqs, "http://testQueue");
Message<String> message = MessageBuilder.withPayload("Hello").build();
UUID uuid = (UUID) message.getHeaders().get(MessageHeaders.ID);
ArgumentCaptor<SendMessageRequest> sendMessageRequestArgumentCaptor = ArgumentCaptor.forClass(SendMessageRequest.class);
when(amazonSqs.sendMessage(sendMessageRequestArgumentCaptor.capture())).thenReturn(new SendMessageResult());
// Act
boolean sent = messageChannel.send(message);
// Assert
assertTrue(sent);
assertEquals(uuid.toString(), sendMessageRequestArgumentCaptor.getValue().getMessageAttributes().get(MessageHeaders.ID).getStringValue());
}
@Test
public void receiveMessage_withIdOfTypeString_IdShouldBeConvertedToUuid() throws Exception {
// Arrange
AmazonSQSAsync amazonSqs = mock(AmazonSQSAsync.class);
UUID uuid = UUID.randomUUID();
when(amazonSqs.receiveMessage(new ReceiveMessageRequest("http://testQueue").
withWaitTimeSeconds(0).
withMaxNumberOfMessages(1).
withAttributeNames(QueueMessageChannel.ATTRIBUTE_NAMES).
withMessageAttributeNames("All"))).
thenReturn(new ReceiveMessageResult().withMessages(new com.amazonaws.services.sqs.model.Message().withBody("Hello").
withMessageAttributes(Collections.singletonMap(MessageHeaders.ID,
new MessageAttributeValue().withDataType(MessageAttributeDataTypes.STRING).withStringValue(uuid.toString())))));
PollableChannel messageChannel = new QueueMessageChannel(amazonSqs, "http://testQueue");
// Act
Message<?> receivedMessage = messageChannel.receive();
// Assert
Object idMessageHeader = receivedMessage.getHeaders().get(MessageHeaders.ID);
assertTrue(UUID.class.isInstance(idMessageHeader));
assertEquals(uuid, idMessageHeader);
}
@Test
@SuppressWarnings("unchecked")
public void sendMessage_withTimeout_sendsMessageAsyncAndReturnsTrueOnceFutureCompleted() throws Exception {
// Arrange
Future<SendMessageResult> future = mock(Future.class);
when(future.get(1000, TimeUnit.MILLISECONDS)).thenReturn(new SendMessageResult());
AmazonSQSAsync amazonSqs = mock(AmazonSQSAsync.class);
when(amazonSqs.sendMessageAsync(any(SendMessageRequest.class))).thenReturn(future);
QueueMessageChannel queueMessageChannel = new QueueMessageChannel(amazonSqs, "http://testQueue");
// Act
boolean result = queueMessageChannel.send(MessageBuilder.withPayload("Hello").build(), 1000);
// Assert
assertTrue(result);
verify(amazonSqs, only()).sendMessageAsync(any(SendMessageRequest.class));
}
@Test
@SuppressWarnings("unchecked")
public void sendMessage_withSendMessageAsyncTakingMoreTimeThanSpecifiedTimeout_returnsFalse() throws Exception {
// Arrange
Future<SendMessageResult> future = mock(Future.class);
when(future.get(1000, TimeUnit.MILLISECONDS)).thenThrow(new TimeoutException());
AmazonSQSAsync amazonSqs = mock(AmazonSQSAsync.class);
when(amazonSqs.sendMessageAsync(any(SendMessageRequest.class))).thenReturn(future);
QueueMessageChannel queueMessageChannel = new QueueMessageChannel(amazonSqs, "http://testQueue");
// Act
boolean result = queueMessageChannel.send(MessageBuilder.withPayload("Hello").build(), 1000);
// Assert
assertFalse(result);
}
@Test
@SuppressWarnings("unchecked")
public void sendMessage_withExecutionExceptionWhileSendingAsyncMessage_throwMessageDeliveryException() throws Exception {
// Arrange
Future<SendMessageResult> future = mock(Future.class);
when(future.get(1000, TimeUnit.MILLISECONDS)).thenThrow(new ExecutionException(new Exception()));
AmazonSQSAsync amazonSqs = mock(AmazonSQSAsync.class);
when(amazonSqs.sendMessageAsync(any(SendMessageRequest.class))).thenReturn(future);
QueueMessageChannel queueMessageChannel = new QueueMessageChannel(amazonSqs, "http://testQueue");
// Assert
this.expectedException.expect(MessageDeliveryException.class);
// Act
queueMessageChannel.send(MessageBuilder.withPayload("Hello").build(), 1000);
}
@Test
public void sendMessage_withDelayHeader_shouldSetDelayOnSendMessageRequestAndNotSetItAsHeaderAsMessageAttribute() throws Exception {
// Arrange
AmazonSQSAsync amazonSqs = mock(AmazonSQSAsync.class);
ArgumentCaptor<SendMessageRequest> sendMessageRequestArgumentCaptor = ArgumentCaptor.forClass(SendMessageRequest.class);
when(amazonSqs.sendMessage(sendMessageRequestArgumentCaptor.capture())).thenReturn(new SendMessageResult());
QueueMessageChannel queueMessageChannel = new QueueMessageChannel(amazonSqs, "http://testQueue");
Message<String> message = MessageBuilder.withPayload("Hello").setHeader(SqsMessageHeaders.SQS_DELAY_HEADER, 15).build();
// Act
queueMessageChannel.send(message);
// Assert
SendMessageRequest sendMessageRequest = sendMessageRequestArgumentCaptor.getValue();
assertEquals(new Integer(15), sendMessageRequest.getDelaySeconds());
assertFalse(sendMessageRequest.getMessageAttributes().containsKey(SqsMessageHeaders.SQS_DELAY_HEADER));
}
@Test
public void sendMessage_withoutDelayHeader_shouldNotSetDelayOnSendMessageRequestAndNotSetHeaderAsMessageAttribute() throws Exception {
// Arrange
AmazonSQSAsync amazonSqs = mock(AmazonSQSAsync.class);
ArgumentCaptor<SendMessageRequest> sendMessageRequestArgumentCaptor = ArgumentCaptor.forClass(SendMessageRequest.class);
when(amazonSqs.sendMessage(sendMessageRequestArgumentCaptor.capture())).thenReturn(new SendMessageResult());
QueueMessageChannel queueMessageChannel = new QueueMessageChannel(amazonSqs, "http://testQueue");
Message<String> message = MessageBuilder.withPayload("Hello").build();
// Act
queueMessageChannel.send(message);
// Assert
SendMessageRequest sendMessageRequest = sendMessageRequestArgumentCaptor.getValue();
assertNull(sendMessageRequest.getDelaySeconds());
assertFalse(sendMessageRequest.getMessageAttributes().containsKey(SqsMessageHeaders.SQS_DELAY_HEADER));
}
}