プロジェクトでRabbitMQを使用しています。
コンシューマーにrabbitMQのクライアント部分のコードがあり、実際のMQに接続するには接続にtls1.1が必要です。
このコードをJUnitテストでテストし、コンシューマーへのメッセージ配信をモックしたいと思います。
ラクダのウサギまたはactiveMQがどのように異なるツールを使用したいくつかの例をグーグルで見ていますが、このツールはamqp 1.0で動作し、rabbitMQはamqp0.9でのみ動作します。
誰かがこの問題を抱えていましたか?
ありがとう!
更新
これは、キューからjsonを受信するためのテストのコードです。
package com.foo.foo.queue;
import Java.io.File;
import Java.io.FileInputStream;
import Java.io.IOException;
import Java.net.URL;
import Java.security.*;
import Java.security.cert.CertificateException;
import javax.net.ssl.*;
import org.Apache.commons.lang3.StringUtils;
import org.Apache.log4j.LogManager;
import org.Apache.log4j.Logger;
import org.json.JSONObject;
import com.foo.foo.Constants.Constants;
import com.foo.foo.core.ConfigurationContainer;
import com.foo.foo.policyfinders.PolicyFinder;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.QueueingConsumer;
public class BrokerThreadHLConsumer extends Thread {
private static BrokerThreadHLConsumer instance;
private static final Logger log = LogManager.getLogger(BrokerThreadHLConsumer.class);
private Channel channel;
private String queueName;
private PolicyFinder PolicyFinder;
private Connection connection;
private QueueingConsumer consumer;
private boolean loop;
private BrokerThreadHLConsumer() throws IOException {
ConnectionFactory factory = new ConnectionFactory();
char[] keyPassphrase = "clientrabbit".toCharArray();
KeyStore keyStoreCacerts;
ConfigurationContainer configurationContainer = ConfigurationContainer.getInstance();
String exchangeName = configurationContainer.getProperty(Constants.EXCHANGE_NAME);
String rabbitHost = configurationContainer.getProperty(Constants.RABBITMQ_SERVER_Host_VALUE);
try {
/* Public key cacerts to connect to message queue*/
keyStoreCacerts = KeyStore.getInstance("PKCS12");
URL resourcePublicKey = this.getClass().getClassLoader().getResource("certs/client.keycert.p12");
File filePublicKey = new File(resourcePublicKey.toURI());
keyStoreCacerts.load(new FileInputStream(filePublicKey), keyPassphrase);
KeyManagerFactory keyManager;
keyManager = KeyManagerFactory.getInstance("SunX509");
keyManager.init(keyStoreCacerts, keyPassphrase);
char[] trustPassphrase = "changeit".toCharArray();
KeyStore tks;
tks = KeyStore.getInstance("JCEKS");
URL resourceCacerts = this.getClass().getClassLoader().getResource("certs/cacerts");
File fileCacerts = new File(resourceCacerts.toURI());
tks.load(new FileInputStream(fileCacerts), trustPassphrase);
TrustManagerFactory tmf;
tmf = TrustManagerFactory.getInstance("SunX509");
tmf.init(tks);
SSLContext c = SSLContext.getInstance("TLSv1.1");
c.init(keyManager.getKeyManagers(), tmf.getTrustManagers(), null);
factory.setUri(rabbitHost);
factory.useSslProtocol(c);
connection = factory.newConnection();
channel = connection.createChannel();
channel.exchangeDeclare(exchangeName, "fanout");
queueName = channel.queueDeclare().getQueue();
channel.queueBind(queueName, exchangeName, "");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (CertificateException e) {
e.printStackTrace();
} catch (KeyStoreException e) {
e.printStackTrace();
} catch (UnrecoverableKeyException e) {
e.printStackTrace();
} catch (KeyManagementException e1) {
e1.printStackTrace();
} catch (Exception e) {
log.error("Couldn't instantiate a channel with the broker installed in " + rabbitHost);
log.error(e.getStackTrace());
e.printStackTrace();
}
}
public static BrokerThreadHLConsumer getInstance() throws CertificateException, UnrecoverableKeyException, NoSuchAlgorithmException, KeyStoreException, KeyManagementException, IOException {
if (instance == null)
instance = new BrokerThreadHLConsumer();
return instance;
}
public void run() {
if (PolicyFinder != null) {
try {
consumer = new QueueingConsumer(channel);
channel.basicConsume(queueName, true, consumer);
log.info("Consumer broker started and waiting for messages");
loop = true;
while (loop) {
try {
QueueingConsumer.Delivery delivery = consumer.nextDelivery();
String message = new String(delivery.getBody());
JSONObject obj = new JSONObject(message);
log.info("Message received from broker " + obj);
if (StringUtils.isNotEmpty(message) && !PolicyFinder.managePolicySet(obj)) {
log.error("PolicySet error: error upgrading the policySet");
}
} catch (Exception e) {
log.error("Receiving message error");
log.error(e);
}
}
} catch (IOException e) {
log.error("Consumer couldn't start");
log.error(e.getStackTrace());
}
} else {
log.error("Consumer couldn't start cause of PolicyFinder is null");
}
}
public void close() {
loop = false;
try {
consumer.getChannel().basicCancel(consumer.getConsumerTag());
} catch (IOException e) {
e.printStackTrace();
}
try {
channel.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
connection.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public void setLuxPolicyFinder(PolicyFinder PolicyFinder) {
this.PolicyFinder = PolicyFinder;
}
}
私が理解しているように、この質問でテストしようとしていることが2つあります。
1つ目は、TLS自体がテストされているため、正しいトラストストアが構成されたRabbitMQの実際のインスタンスに接続するだけで、構成が機能していることが証明されます。
ただし、2つ目は、アプリの機能を実証するテスト(読みやすさのためにCucumberなどのツールを使用)の場合、私が取り組んでいるライブラリを試すことができます: rabbitmq-mock (そしてそれが私が古い投稿を掘り起こす)
依存関係として含めるだけです。
_<dependency>
<groupId>com.github.fridujo</groupId>
<artifactId>rabbitmq-mock</artifactId>
<version>1.0.10</version>
<scope>test</scope>
</dependency>
_
そして、ユニットテストでnew ConnectionFactory()
をnew MockConnectionFactory()
に置き換えます。
プロジェクトでサンプルを入手できます: https://github.com/fridujo/rabbitmq-mock/blob/master/src/test/Java/com/github/fridujo/rabbitmq/mock/IntegrationTest.Java ==
今のところ答えがないので、それは古い質問です。同じ質問で私を大いに助けたのは、次のブログ投稿です: https://tamasgyorfi.net/2016/04/21/writing-integration-tests-for-rabbitmq-based-components/ =。 Apache QPID(OPで提案されているActiveMQではない)を使用し、AMQP0.9.1をサポートしています。
だからここに私がそれをした方法があります、必要なクラス実装の詳細を隠す過程でいくつかのものがあちこちにあるかもしれません、しかしあなたはヒントを得るでしょう! :)
send()
の呼び出しが行われているかどうか! public class SomeClassTest {
private Config config;
private RmqConfig rmqConfig;
private static final ObjectMapper mapper = new ObjectMapper();
private JasperServerClient jasperServerClient;
// @Mock
@InjectMocks
private RabbitMQProducer rabbitMQProducer;
private Connection phoenixConnection;
private String targetNotificationMessage;
SomeClass someClassObject;
@Before
public void setUp() {
// Mock basic stuffs
config = mock(Config.class);
Connection = mock(Connection.class);
rabbitMQProducer = mock(RabbitMQProducer.class); // Imp
jasperServerClient = mock(JasperServerClient.class);
rmqConfig = RmqConfig.builder()
.Host("localhost")
.port(5672)
.userName("guest")
.password("guest")
.queueName("somequeue_name")
.prefetch(1)
.build();
final String randomMessage = "This is a waste message";
Message mockMsg = Message.forSending(randomMessage.getBytes(), null, rmqConfig.getQueueName(), rmqConfig.getQueueName(), "text/plain", "UTF-8", true); // prepare a mock message
// Prepare service configs
ConnectionConfig connectionConfig = RmqConfigUtil.getConfig(rmqConfig);
ProducerConfig producerConfig = new ProducerConfigBuilder()
.exchange(rmqConfig.getQueueName())
.contentType("text/pain")
.contentEncoding("UTF-8")
.connection(connectionConfig).build();
rabbitMQProducer.open(croducerConfig.asMap());
// build the major stuff where the code resides
someClassObject = SomeClass.builder()
.phoenixConnection(phoenixConnection)
.userExchangeName(rmqConfig.getQueueName())
.userRabbitMQProducer(rabbitMQProducer)
.ftpConfig(config.getFtpConfig())
.jasperServerClient(jasperServerClient)
.objectMapper(new ObjectMapper())
.build();
MockitoAnnotations.initMocks(this);
}
@Test
public void testNotificationPub() throws Exception {
// Prepare expected Values
targetNotificationMessage = <<some message>>
// Reflection - my target functions were private
Class cls = Class.forName("com.some.path.to.class");
Object[] objForGetMessage = {<<stuffs>>, <<stuffs>>};
Method getNotificationMessage = cls.getDeclaredMethod("private_fn_1", <<some class>>.class, <<some class>>.class);
Method pubNotification = cls.getDeclaredMethod("private_fn_2", <<some class>>.class, RabbitMQProducer.class, String.class);
getNotificationMessage.setAccessible(true);
pubNotification.setAccessible(true);
// Test Case #1
final <<some class>> notificationMessage = (<<some class>>)getNotificationMessage.invoke(someClassObject, objForGetMessage);
assertEquals(notificationMessage.getMessage(), targetNotificationMessage);
// Test Case #2 - this does RMQ call
Object[] objPubMessage = {notificationMessage, rabbitMQProducer, rmqConfig.getQueueName()};
final Object publishNotification = pubNotification.invoke(someClassObject, objPubMessage);
assertEquals(publishNotificationResp, publishNotification); //viola
//Important, since RabbitMQProducer is mocked, we need to checkup if function call is made to "send" function which send data to RMQ
verify(rabbitMQProducer,times(1)).send(any());
}
@Test
public void testMockCreation(){
assertNotNull(rmqConfig);
assertNotNull(config);
}