BAEL-4769 Additions for 'Querying the Query Model in Axon' (#12578)
* Update to latest and include script to start axon server * Add the two other types of queries * Add unit and integration tests for the queries * BAEL-4769 Formatting Co-authored-by: bipster <openbip@gmail.com>
This commit is contained in:
+171
@@ -0,0 +1,171 @@
|
||||
package com.baeldung.axon.querymodel;
|
||||
|
||||
import com.baeldung.axon.coreapi.events.OrderConfirmedEvent;
|
||||
import com.baeldung.axon.coreapi.events.OrderCreatedEvent;
|
||||
import com.baeldung.axon.coreapi.events.OrderShippedEvent;
|
||||
import com.baeldung.axon.coreapi.events.ProductAddedEvent;
|
||||
import com.baeldung.axon.coreapi.events.ProductCountDecrementedEvent;
|
||||
import com.baeldung.axon.coreapi.events.ProductCountIncrementedEvent;
|
||||
import com.baeldung.axon.coreapi.events.ProductRemovedEvent;
|
||||
import com.baeldung.axon.coreapi.queries.FindAllOrderedProductsQuery;
|
||||
import com.baeldung.axon.coreapi.queries.Order;
|
||||
import com.baeldung.axon.coreapi.queries.OrderStatus;
|
||||
import com.baeldung.axon.coreapi.queries.OrderUpdatesQuery;
|
||||
import com.baeldung.axon.coreapi.queries.TotalProductsShippedQuery;
|
||||
import org.axonframework.queryhandling.QueryUpdateEmitter;
|
||||
import org.junit.jupiter.api.*;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
public abstract class AbstractOrdersEventHandlerUnitTest {
|
||||
|
||||
private static final String ORDER_ID_1 = UUID.randomUUID().toString();
|
||||
private static final String ORDER_ID_2 = UUID.randomUUID().toString();
|
||||
private static final String PRODUCT_ID_1 = UUID.randomUUID().toString();
|
||||
private static final String PRODUCT_ID_2 = UUID.randomUUID().toString();
|
||||
private OrdersEventHandler handler;
|
||||
private static Order orderOne;
|
||||
private static Order orderTwo;
|
||||
QueryUpdateEmitter emitter = mock(QueryUpdateEmitter.class);
|
||||
|
||||
@BeforeAll
|
||||
static void createOrders() {
|
||||
orderOne = new Order(ORDER_ID_1);
|
||||
orderOne.getProducts().put(PRODUCT_ID_1, 3);
|
||||
orderOne.setOrderShipped();
|
||||
|
||||
orderTwo = new Order(ORDER_ID_2);
|
||||
orderTwo.getProducts().put(PRODUCT_ID_1, 1);
|
||||
orderTwo.getProducts().put(PRODUCT_ID_2, 1);
|
||||
orderTwo.setOrderConfirmed();
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
handler = getHandler();
|
||||
}
|
||||
|
||||
protected abstract OrdersEventHandler getHandler();
|
||||
|
||||
@Test
|
||||
void givenTwoOrdersPlacedOfWhichOneNotShipped_whenFindAllOrderedProductsQuery_thenCorrectOrdersAreReturned() {
|
||||
resetWithTwoOrders();
|
||||
|
||||
List<Order> result = handler.handle(new FindAllOrderedProductsQuery());
|
||||
|
||||
assertNotNull(result);
|
||||
assertEquals(2, result.size());
|
||||
|
||||
Order order_1 = result.stream().filter(o -> o.getOrderId().equals(ORDER_ID_1)).findFirst().orElse(null);
|
||||
assertEquals(orderOne, order_1);
|
||||
|
||||
Order order_2 = result.stream().filter(o -> o.getOrderId().equals(ORDER_ID_2)).findFirst().orElse(null);
|
||||
assertEquals(orderTwo, order_2);
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenNoOrdersPlaced_whenTotalProductsShippedQuery_thenZeroReturned() {
|
||||
assertEquals(0, handler.handle(new TotalProductsShippedQuery(PRODUCT_ID_1)));
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenTwoOrdersPlacedOfWhichOneNotShipped_whenTotalProductsShippedQuery_thenOnlyCountProductsFirstOrder() {
|
||||
resetWithTwoOrders();
|
||||
|
||||
assertEquals(3, handler.handle(new TotalProductsShippedQuery(PRODUCT_ID_1)));
|
||||
assertEquals(0, handler.handle(new TotalProductsShippedQuery(PRODUCT_ID_2)));
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenTwoOrdersPlacedAndShipped_whenTotalProductsShippedQuery_thenCountBothOrders() {
|
||||
resetWithTwoOrders();
|
||||
handler.on(new OrderShippedEvent(ORDER_ID_2));
|
||||
|
||||
assertEquals(4, handler.handle(new TotalProductsShippedQuery(PRODUCT_ID_1)));
|
||||
assertEquals(1, handler.handle(new TotalProductsShippedQuery(PRODUCT_ID_2)));
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenOrderExist_whenOrderUpdatesQuery_thenOrderReturned() {
|
||||
resetWithTwoOrders();
|
||||
|
||||
Order result = handler.handle(new OrderUpdatesQuery(ORDER_ID_1));
|
||||
assertNotNull(result);
|
||||
assertEquals(ORDER_ID_1, result.getOrderId());
|
||||
assertEquals(3, result.getProducts().get(PRODUCT_ID_1));
|
||||
assertEquals(OrderStatus.SHIPPED, result.getOrderStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenOrderExist_whenProductAddedEvent_thenUpdateEmittedOnce() {
|
||||
handler.on(new OrderCreatedEvent(ORDER_ID_1));
|
||||
|
||||
handler.on(new ProductAddedEvent(ORDER_ID_1, PRODUCT_ID_1));
|
||||
|
||||
verify(emitter, times(1)).emit(eq(OrderUpdatesQuery.class), any(), any(Order.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenOrderWithProductExist_whenProductCountDecrementedEvent_thenUpdateEmittedOnce() {
|
||||
handler.on(new OrderCreatedEvent(ORDER_ID_1));
|
||||
handler.on(new ProductAddedEvent(ORDER_ID_1, PRODUCT_ID_1));
|
||||
reset(emitter);
|
||||
|
||||
handler.on(new ProductCountDecrementedEvent(ORDER_ID_1, PRODUCT_ID_1));
|
||||
|
||||
verify(emitter, times(1)).emit(eq(OrderUpdatesQuery.class), any(), any(Order.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenOrderWithProductExist_whenProductRemovedEvent_thenUpdateEmittedOnce() {
|
||||
handler.on(new OrderCreatedEvent(ORDER_ID_1));
|
||||
handler.on(new ProductAddedEvent(ORDER_ID_1, PRODUCT_ID_1));
|
||||
reset(emitter);
|
||||
|
||||
handler.on(new ProductRemovedEvent(ORDER_ID_1, PRODUCT_ID_1));
|
||||
|
||||
verify(emitter, times(1)).emit(eq(OrderUpdatesQuery.class), any(), any(Order.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenOrderWithProductExist_whenProductCountIncrementedEvent_thenUpdateEmittedOnce() {
|
||||
handler.on(new OrderCreatedEvent(ORDER_ID_1));
|
||||
handler.on(new ProductAddedEvent(ORDER_ID_1, PRODUCT_ID_1));
|
||||
reset(emitter);
|
||||
|
||||
handler.on(new ProductCountIncrementedEvent(ORDER_ID_1, PRODUCT_ID_1));
|
||||
|
||||
verify(emitter, times(1)).emit(eq(OrderUpdatesQuery.class), any(), any(Order.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenOrderWithProductExist_whenOrderConfirmedEvent_thenUpdateEmittedOnce() {
|
||||
handler.on(new OrderCreatedEvent(ORDER_ID_1));
|
||||
handler.on(new ProductAddedEvent(ORDER_ID_1, PRODUCT_ID_1));
|
||||
reset(emitter);
|
||||
|
||||
handler.on(new OrderConfirmedEvent(ORDER_ID_1));
|
||||
|
||||
verify(emitter, times(1)).emit(eq(OrderUpdatesQuery.class), any(), any(Order.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenOrderWithProductAndConfirmationExist_whenOrderShippedEvent_thenUpdateEmittedOnce() {
|
||||
handler.on(new OrderCreatedEvent(ORDER_ID_1));
|
||||
handler.on(new ProductAddedEvent(ORDER_ID_1, PRODUCT_ID_1));
|
||||
reset(emitter);
|
||||
|
||||
handler.on(new OrderShippedEvent(ORDER_ID_1));
|
||||
|
||||
verify(emitter, times(1)).emit(eq(OrderUpdatesQuery.class), any(), any(Order.class));
|
||||
}
|
||||
|
||||
private void resetWithTwoOrders() {
|
||||
handler.reset(Arrays.asList(orderOne, orderTwo));
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
package com.baeldung.axon.querymodel;
|
||||
|
||||
public class InMemoryOrdersEventHandlerUnitTest extends AbstractOrdersEventHandlerUnitTest {
|
||||
|
||||
@Override
|
||||
protected OrdersEventHandler getHandler() {
|
||||
return new InMemoryOrdersEventHandler(emitter);
|
||||
}
|
||||
}
|
||||
+129
@@ -0,0 +1,129 @@
|
||||
package com.baeldung.axon.querymodel;
|
||||
|
||||
import com.baeldung.axon.OrderApplication;
|
||||
import com.baeldung.axon.coreapi.events.OrderConfirmedEvent;
|
||||
import com.baeldung.axon.coreapi.events.OrderShippedEvent;
|
||||
import com.baeldung.axon.coreapi.events.ProductAddedEvent;
|
||||
import com.baeldung.axon.coreapi.events.ProductCountDecrementedEvent;
|
||||
import com.baeldung.axon.coreapi.events.ProductCountIncrementedEvent;
|
||||
import com.baeldung.axon.coreapi.queries.Order;
|
||||
|
||||
import org.axonframework.eventhandling.gateway.EventGateway;
|
||||
import org.junit.jupiter.api.*;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
|
||||
import reactor.test.StepVerifier;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
@SpringBootTest(classes = OrderApplication.class)
|
||||
class OrderQueryServiceIntegrationTest {
|
||||
|
||||
@Autowired
|
||||
OrderQueryService queryService;
|
||||
|
||||
@Autowired
|
||||
EventGateway eventGateway;
|
||||
|
||||
@Autowired
|
||||
OrdersEventHandler handler;
|
||||
|
||||
private String orderId;
|
||||
private final String productId = "Deluxe Chair";
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
orderId = UUID.randomUUID()
|
||||
.toString();
|
||||
Order order = new Order(orderId);
|
||||
handler.reset(Collections.singletonList(order));
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenOrderCreatedEventSend_whenCallingAllOrders_thenOneCreatedOrderIsReturned() throws ExecutionException, InterruptedException {
|
||||
List<OrderResponse> result = queryService.findAllOrders()
|
||||
.get();
|
||||
assertEquals(1, result.size());
|
||||
OrderResponse response = result.get(0);
|
||||
assertEquals(orderId, response.getOrderId());
|
||||
assertEquals(OrderStatusResponse.CREATED, response.getOrderStatus());
|
||||
assertTrue(response.getProducts()
|
||||
.isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenThreeDeluxeChairsShipped_whenCallingAllShippedChairs_then234PlusTreeIsReturned() {
|
||||
Order order = new Order(orderId);
|
||||
order.getProducts()
|
||||
.put(productId, 3);
|
||||
order.setOrderShipped();
|
||||
handler.reset(Collections.singletonList(order));
|
||||
|
||||
assertEquals(237, queryService.totalShipped(productId));
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenOrdersAreUpdated_whenCallingOrderUpdates_thenUpdatesReturned() {
|
||||
ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
|
||||
executor.schedule(this::addIncrementDecrementConfirmAndShip, 100L, TimeUnit.MILLISECONDS);
|
||||
try {
|
||||
StepVerifier.create(queryService.orderUpdates(orderId))
|
||||
.assertNext(order -> assertTrue(order.getProducts()
|
||||
.isEmpty()))
|
||||
.assertNext(order -> assertEquals(1, order.getProducts()
|
||||
.get(productId)))
|
||||
.assertNext(order -> assertEquals(2, order.getProducts()
|
||||
.get(productId)))
|
||||
.assertNext(order -> assertEquals(1, order.getProducts()
|
||||
.get(productId)))
|
||||
.assertNext(order -> assertEquals(OrderStatusResponse.CONFIRMED, order.getOrderStatus()))
|
||||
.assertNext(order -> assertEquals(OrderStatusResponse.SHIPPED, order.getOrderStatus()))
|
||||
.thenCancel()
|
||||
.verify();
|
||||
} finally {
|
||||
executor.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
private void addIncrementDecrementConfirmAndShip() {
|
||||
sendProductAddedEvent();
|
||||
sendProductCountIncrementEvent();
|
||||
sendProductCountDecrementEvent();
|
||||
sendOrderConfirmedEvent();
|
||||
sendOrderShippedEvent();
|
||||
}
|
||||
|
||||
private void sendProductAddedEvent() {
|
||||
ProductAddedEvent event = new ProductAddedEvent(orderId, productId);
|
||||
eventGateway.publish(event);
|
||||
}
|
||||
|
||||
private void sendProductCountIncrementEvent() {
|
||||
ProductCountIncrementedEvent event = new ProductCountIncrementedEvent(orderId, productId);
|
||||
eventGateway.publish(event);
|
||||
}
|
||||
|
||||
private void sendProductCountDecrementEvent() {
|
||||
ProductCountDecrementedEvent event = new ProductCountDecrementedEvent(orderId, productId);
|
||||
eventGateway.publish(event);
|
||||
}
|
||||
|
||||
private void sendOrderConfirmedEvent() {
|
||||
OrderConfirmedEvent event = new OrderConfirmedEvent(orderId);
|
||||
eventGateway.publish(event);
|
||||
}
|
||||
|
||||
private void sendOrderShippedEvent() {
|
||||
OrderShippedEvent event = new OrderShippedEvent(orderId);
|
||||
eventGateway.publish(event);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
axon.axonserver.enabled=false
|
||||
Reference in New Issue
Block a user