Skip to content

Commit

Permalink
[#1761] Add tests and documentation for the AMQP Adapter Client.
Browse files Browse the repository at this point in the history
Signed-off-by: Abel Buechner-Mihaljevic <abel.buechner-mihaljevic@bosch.io>
  • Loading branch information
b-abel committed Mar 18, 2020
1 parent d7c0f3d commit 7ae1740
Show file tree
Hide file tree
Showing 12 changed files with 864 additions and 7 deletions.
Expand Up @@ -75,6 +75,7 @@ public static Future<MessageConsumer> create(
final String deviceId,
final BiConsumer<ProtonDelivery, Message> messageHandler) {

Objects.requireNonNull(con);
Objects.requireNonNull(tenantId);
Objects.requireNonNull(deviceId);
Objects.requireNonNull(messageHandler);
Expand All @@ -99,6 +100,7 @@ public static Future<MessageConsumer> create(
final HonoConnection con,
final BiConsumer<ProtonDelivery, Message> messageHandler) {

Objects.requireNonNull(con);
Objects.requireNonNull(messageHandler);

final ResourceIdentifier address = ResourceIdentifier
Expand Down Expand Up @@ -164,4 +166,9 @@ private void setReceiver(final ProtonReceiver protonReceiver) {
receiver = protonReceiver;
}

// visible for testing
ProtonReceiver getReceiver() {
return receiver;
}

}
@@ -0,0 +1,87 @@
/*******************************************************************************
* Copyright (c) 2020 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*******************************************************************************/

package org.eclipse.hono.client;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import java.util.Collections;
import java.util.Map;

import org.apache.qpid.proton.message.Message;
import org.eclipse.hono.client.impl.HonoClientUnitTestHelper;
import org.eclipse.hono.util.MessageHelper;
import org.junit.jupiter.api.BeforeEach;
import org.mockito.ArgumentCaptor;

import io.vertx.core.Future;
import io.vertx.core.Vertx;
import io.vertx.proton.ProtonSender;

/**
* Base class for tests of the downstream senders of the AMQP Adapter client.
*
*/
public abstract class AbstractAmqpAdapterClientDownstreamSenderTestBase {

protected final String tenantId = "test-tenant";
protected final String deviceId = "test-device";
protected final String contentType = "text/plain";
protected final byte[] payload = "test-value".getBytes();
protected final String testPropertyKey = "test-key";
protected final String testPropertyValue = "test-value";
protected final Map<String, ?> applicationProperties = Collections.singletonMap(testPropertyKey, testPropertyValue);

protected ProtonSender sender;
protected HonoConnection connection;
protected ArgumentCaptor<Message> messageArgumentCaptor;

/**
* Sets up fixture.
*/
@BeforeEach
public void setUp() {
sender = HonoClientUnitTestHelper.mockProtonSender();
final Vertx vertx = mock(Vertx.class);
connection = HonoClientUnitTestHelper.mockHonoConnection(vertx);
when(connection.createSender(any(), any(), any())).thenReturn(Future.succeededFuture(sender));
messageArgumentCaptor = ArgumentCaptor.forClass(Message.class);
}

/**
* Executes the assertions that checkthat the message produced conforms to the expectations of the AMQP adapter.
*
* @param expectedAddress The expected target address.
*/
protected void assertMessageConformsAmqpAdapterSpec(final String expectedAddress) {

verify(sender).send(messageArgumentCaptor.capture(), any());

final Message message = messageArgumentCaptor.getValue();

assertThat(message.getAddress()).isEqualTo(expectedAddress);

assertThat(MessageHelper.getPayloadAsString(message)).isEqualTo(new String(payload));
assertThat(message.getContentType()).isEqualTo(contentType);

final Map<String, Object> applicationProperties = message.getApplicationProperties().getValue();
assertThat(applicationProperties.get(testPropertyKey)).isEqualTo(testPropertyValue);

assertThat(applicationProperties.get("device_id")).isEqualTo(deviceId);
}

}
@@ -0,0 +1,119 @@
/*******************************************************************************
* Copyright (c) 2020 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*******************************************************************************/

package org.eclipse.hono.client.device.amqp;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import org.eclipse.hono.client.HonoConnection;
import org.eclipse.hono.client.MessageConsumer;
import org.eclipse.hono.client.impl.HonoClientUnitTestHelper;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;

import io.vertx.core.Future;
import io.vertx.core.Vertx;
import io.vertx.proton.ProtonReceiver;
import io.vertx.proton.ProtonSender;

/**
* Tests verifying behavior of {@link AmqpAdapterClientFactory}.
*
*/
public class AmqpAdapterClientFactoryTest {

private static AmqpAdapterClientFactory factory;

/**
* Sets up the fixture.
*/
@BeforeAll
public static void setUp() {

final HonoConnection connection = HonoClientUnitTestHelper.mockHonoConnection(mock(Vertx.class));
when(connection.isConnected(anyLong())).thenReturn(Future.succeededFuture());

final ProtonSender protonSender = HonoClientUnitTestHelper.mockProtonSender();
when(connection.createSender(any(), any(), any())).thenReturn(Future.succeededFuture(protonSender));

final ProtonReceiver receiver = HonoClientUnitTestHelper.mockProtonReceiver();
when(connection.createReceiver(anyString(), any(), any(), any())).thenReturn(Future.succeededFuture(receiver));

factory = AmqpAdapterClientFactory.create(connection, "my-tenant");
}

/**
* Verifies that the factories create method returned an instance.
*/
@Test
public void testCreateReturnsInstance() {
assertThat(factory).isNotNull();
}

/**
* Verifies that a telemetry sender instance is returned.
*/
@Test
public void testGetOrCreateTelemetrySenderReturnsInstance() {
final Future<TelemetrySender> sender = factory.getOrCreateTelemetrySender();
assertThat(sender.succeeded());
assertThat(sender.result()).isNotNull();
}

/**
* Verifies that an event sender instance is returned.
*/
@Test
public void testGetOrCreateEventSenderReturnsInstance() {
final Future<EventSender> sender = factory.getOrCreateEventSender();
assertThat(sender.succeeded());
assertThat(sender.result()).isNotNull();
}

/**
* Verifies that a device scoped command consumer instance is returned.
*/
@Test
public void testCreateDeviceSpecificCommandConsumerReturnsInstance() {
final Future<MessageConsumer> commandConsumer = factory.createDeviceSpecificCommandConsumer("my-device", x -> {
});
assertThat(commandConsumer.succeeded());
assertThat(commandConsumer.result()).isNotNull();
}

/**
* Verifies that a command consumer instance is returned.
*/
@Test
public void testCreateCommandConsumerReturnsInstance() {
final Future<MessageConsumer> commandConsumer = factory.createCommandConsumer(x -> {
});
assertThat(commandConsumer.succeeded());
assertThat(commandConsumer.result()).isNotNull();
}

/**
* Verifies that a command response sender instance is returned.
*/
@Test
public void testGetOrCreateCommandResponseSender() {
final Future<CommandResponder> responseSender = factory.getOrCreateCommandResponseSender();
assertThat(responseSender.succeeded());
assertThat(responseSender.result()).isNotNull();
}
}
@@ -0,0 +1,56 @@
/*******************************************************************************
* Copyright (c) 2020 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*******************************************************************************/

package org.eclipse.hono.client.device.amqp;

import static org.assertj.core.api.Assertions.assertThat;

import org.eclipse.hono.client.AbstractAmqpAdapterClientDownstreamSenderTestBase;
import org.eclipse.hono.client.device.amqp.internal.AmqpAdapterClientCommandResponseSender;
import org.junit.jupiter.api.Test;

import io.vertx.core.Future;
import io.vertx.proton.ProtonDelivery;

/**
* Verifies behavior of {@link CommandResponder}.
*
*/
public class CommandResponderTest extends AbstractAmqpAdapterClientDownstreamSenderTestBase {

/**
* Verifies that the message produced conforms to the expectations of the AMQP adapter.
*/
@Test
public void testMessageIsValid() {

// GIVEN a CommandResponder instance
final CommandResponder commandResponder = AmqpAdapterClientCommandResponseSender
.createWithAnonymousLinkAddress(connection, tenantId, s -> {
}).result();

// WHEN sending a message using the API
final String targetAddress = "command_response/test-tenant/test-device/123";
final String correlationId = "0";
final int status = 200;
final Future<ProtonDelivery> deliveryFuture = commandResponder.sendCommandResponse(deviceId, targetAddress,
correlationId, status, payload, contentType,
applicationProperties);

// THEN the AMQP message produces by the client conforms to the expectations of the AMQP protocol adapter
assertThat(deliveryFuture.succeeded());

assertMessageConformsAmqpAdapterSpec(targetAddress);

}
}
@@ -0,0 +1,53 @@
/*******************************************************************************
* Copyright (c) 2020 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*******************************************************************************/

package org.eclipse.hono.client.device.amqp;

import static org.assertj.core.api.Assertions.assertThat;

import org.eclipse.hono.client.AbstractAmqpAdapterClientDownstreamSenderTestBase;
import org.eclipse.hono.client.device.amqp.internal.AmqpAdapterClientEventSenderImpl;
import org.junit.jupiter.api.Test;

import io.vertx.core.Future;
import io.vertx.proton.ProtonDelivery;

/**
* Verifies behavior of {@link EventSender}.
*
*/
public class EventSenderTest extends AbstractAmqpAdapterClientDownstreamSenderTestBase {

/**
* Verifies that the message produced conforms to the expectations of the AMQP adapter.
*/
@Test
public void testMessageIsValid() {

// GIVEN a EventSender instance
final EventSender eventSender = AmqpAdapterClientEventSenderImpl
.createWithAnonymousLinkAddress(connection, tenantId, s -> {
}).result();

// WHEN sending a message using the API
final Future<ProtonDelivery> deliveryFuture = eventSender.send(deviceId, payload, contentType,
applicationProperties);

// THEN the AMQP message produces by the client conforms to the expectations of the AMQP protocol adapter
assertThat(deliveryFuture.succeeded());

assertMessageConformsAmqpAdapterSpec("event" + "/" + tenantId + "/" + deviceId);

}

}

0 comments on commit 7ae1740

Please sign in to comment.