/*
* Copyright 2002-2017 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.integration.amqp.channel;
import static org.hamcrest.Matchers.containsString;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.logging.Log;
import org.junit.Test;
import org.springframework.amqp.core.AmqpAdmin;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageListener;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.rabbit.connection.Connection;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
import org.springframework.beans.DirectFieldAccessor;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.integration.test.util.TestUtils;
import org.springframework.messaging.MessageDeliveryException;
import com.rabbitmq.client.AMQP.Queue.DeclareOk;
import com.rabbitmq.client.Channel;
/**
* @author Gary Russell
* @author Artem Bilan
* @since 2.1
*
*/
public class DispatcherHasNoSubscribersTests {
@SuppressWarnings("unchecked")
@Test
public void testPtP() throws Exception {
final Channel channel = mock(Channel.class);
DeclareOk declareOk = mock(DeclareOk.class);
when(declareOk.getQueue()).thenReturn("noSubscribersChannel");
when(channel.queueDeclare(anyString(), anyBoolean(), anyBoolean(), anyBoolean(), isNull()))
.thenReturn(declareOk);
Connection connection = mock(Connection.class);
doAnswer(invocation -> channel).when(connection).createChannel(anyBoolean());
ConnectionFactory connectionFactory = mock(ConnectionFactory.class);
when(connectionFactory.createConnection()).thenReturn(connection);
SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
AmqpTemplate amqpTemplate = mock(AmqpTemplate.class);
PointToPointSubscribableAmqpChannel amqpChannel =
new PointToPointSubscribableAmqpChannel("noSubscribersChannel", container, amqpTemplate);
amqpChannel.setBeanName("noSubscribersChannel");
amqpChannel.setBeanFactory(mock(BeanFactory.class));
amqpChannel.afterPropertiesSet();
MessageListener listener = (MessageListener) container.getMessageListener();
try {
listener.onMessage(new Message("Hello world!".getBytes(), null));
fail("Exception expected");
}
catch (MessageDeliveryException e) {
assertThat(e.getMessage(),
containsString("Dispatcher has no subscribers for amqp-channel 'noSubscribersChannel'."));
}
}
@Test
public void testPubSub() {
final Channel channel = mock(Channel.class);
Connection connection = mock(Connection.class);
doAnswer(invocation -> channel).when(connection).createChannel(anyBoolean());
ConnectionFactory connectionFactory = mock(ConnectionFactory.class);
when(connectionFactory.createConnection()).thenReturn(connection);
SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
AmqpTemplate amqpTemplate = mock(AmqpTemplate.class);
final Queue queue = new Queue("noSubscribersQueue");
PublishSubscribeAmqpChannel amqpChannel = new PublishSubscribeAmqpChannel("noSubscribersChannel",
container, amqpTemplate) {
@Override
protected String obtainQueueName(AmqpAdmin admin,
String channelName) {
return queue.getName();
}
};
amqpChannel.setBeanName("noSubscribersChannel");
amqpChannel.setBeanFactory(mock(BeanFactory.class));
amqpChannel.afterPropertiesSet();
List<String> logList = insertMockLoggerInListener(amqpChannel);
MessageListener listener = (MessageListener) container.getMessageListener();
listener.onMessage(new Message("Hello world!".getBytes(), null));
verifyLogReceived(logList);
}
private List<String> insertMockLoggerInListener(
PublishSubscribeAmqpChannel channel) {
SimpleMessageListenerContainer container = TestUtils.getPropertyValue(
channel, "container", SimpleMessageListenerContainer.class);
Log logger = mock(Log.class);
final ArrayList<String> logList = new ArrayList<String>();
doAnswer(invocation -> {
String message = invocation.getArgument(0);
if (message.startsWith("Dispatcher has no subscribers")) {
logList.add(message);
}
return null;
}).when(logger).warn(anyString(), any(Exception.class));
when(logger.isWarnEnabled()).thenReturn(true);
Object listener = container.getMessageListener();
DirectFieldAccessor dfa = new DirectFieldAccessor(listener);
dfa.setPropertyValue("logger", logger);
return logList;
}
private void verifyLogReceived(final List<String> logList) {
assertTrue("Failed to get expected exception", logList.size() > 0);
boolean expectedExceptionFound = false;
while (logList.size() > 0) {
String message = logList.remove(0);
assertNotNull("Failed to get expected exception", message);
if (message.startsWith("Dispatcher has no subscribers")) {
expectedExceptionFound = true;
assertThat(message,
containsString("Dispatcher has no subscribers for amqp-channel 'noSubscribersChannel'."));
break;
}
}
assertTrue("Failed to get expected exception", expectedExceptionFound);
}
}