package io.pivotal.refarch.cqrs.trader.app.contracts; import io.pivotal.refarch.cqrs.trader.app.controller.QueryController; import io.pivotal.refarch.cqrs.trader.app.query.company.CompanyView; import io.pivotal.refarch.cqrs.trader.app.query.orders.trades.OrderBookView; import io.pivotal.refarch.cqrs.trader.app.query.orders.trades.OrderView; import io.pivotal.refarch.cqrs.trader.app.query.orders.transaction.TradeExecutedView; import io.pivotal.refarch.cqrs.trader.app.query.orders.transaction.TransactionView; import io.pivotal.refarch.cqrs.trader.app.query.portfolio.ItemEntry; import io.pivotal.refarch.cqrs.trader.app.query.portfolio.PortfolioView; import io.pivotal.refarch.cqrs.trader.app.query.users.UserView; import io.pivotal.refarch.cqrs.trader.coreapi.company.CompanyByIdQuery; import io.pivotal.refarch.cqrs.trader.coreapi.company.FindAllCompaniesQuery; import io.pivotal.refarch.cqrs.trader.coreapi.orders.TransactionType; import io.pivotal.refarch.cqrs.trader.coreapi.orders.trades.OrderBookByIdQuery; import io.pivotal.refarch.cqrs.trader.coreapi.orders.trades.OrderBooksByCompanyIdQuery; import io.pivotal.refarch.cqrs.trader.coreapi.orders.transaction.ExecutedTradesByOrderBookIdQuery; import io.pivotal.refarch.cqrs.trader.coreapi.orders.transaction.TransactionByIdQuery; import io.pivotal.refarch.cqrs.trader.coreapi.orders.transaction.TransactionState; import io.pivotal.refarch.cqrs.trader.coreapi.orders.transaction.TransactionsByPortfolioIdQuery; import io.pivotal.refarch.cqrs.trader.coreapi.portfolio.PortfolioByIdQuery; import io.pivotal.refarch.cqrs.trader.coreapi.portfolio.PortfolioByUserIdQuery; import io.pivotal.refarch.cqrs.trader.coreapi.users.FindAllUsersQuery; import io.pivotal.refarch.cqrs.trader.coreapi.users.UserByIdQuery; import io.restassured.module.mockmvc.RestAssuredMockMvc; import org.axonframework.queryhandling.QueryGateway; import org.axonframework.queryhandling.responsetypes.InstanceResponseType; import org.axonframework.queryhandling.responsetypes.MultipleInstancesResponseType; import org.jetbrains.annotations.NotNull; import org.junit.*; import java.util.Collections; import java.util.List; import java.util.concurrent.CompletableFuture; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.Mockito.*; public class QueryContractTest { private static final String ORDER_BOOK_ID = "f82c40ec-a785-11e8-98d0-529269fb1459"; private static final String TRANSACTION_ID = "f82c448e-a785-11e8-98d0-529269fb1459"; private static final String PORTFOLIO_ID = "f82c481c-a785-11e8-98d0-529269fb1459"; private static final String BUY_ORDER_ID = "f82c4984-a785-11e8-98d0-529269fb1459"; private static final String SELL_ORDER_ID = "f82c4ace-a785-11e8-98d0-529269fb1459"; private static final String COMPANY_ID = "f82c40ec-a785-11e8-98d0-529269fb1459"; private static final String COMPANY_NAME = "Pivotal"; private static final String USER_ID = "98684ad8-987e-4d16-8ad8-b620f4320f4c"; private static final String USER_NAME = "Pieter Humphrey"; @SuppressWarnings("unchecked") @Before public void setup() { final QueryGateway queryGateway = mock(QueryGateway.class); // Default to an empty CompletableFuture for InstanceResponseType queries - specify working queries later when(queryGateway.query(any(), any(InstanceResponseType.class))) .thenReturn(CompletableFuture.completedFuture(null)); // Default to a empty List CompletableFuture for MultipleInstancesResponseType queries - specify working queries later when(queryGateway.query(any(), any(MultipleInstancesResponseType.class))) .thenReturn(CompletableFuture.completedFuture(Collections.emptyList())); when(queryGateway.query(argThat(this::matchCompanyByIdQuery), any(InstanceResponseType.class))) .thenReturn(CompletableFuture.completedFuture(buildCompanyView())); when(queryGateway.query(any(FindAllCompaniesQuery.class), any(MultipleInstancesResponseType.class))) .thenReturn(CompletableFuture.completedFuture(buildAllCompaniesView())); when(queryGateway.query(argThat(this::matchOrderBookByIdQuery), any(InstanceResponseType.class))) .thenReturn(CompletableFuture.completedFuture(buildOrderBookView())); when(queryGateway.query(argThat(this::matchOrderBooksByCompanyIdQuery), any(MultipleInstancesResponseType.class))) .thenReturn(CompletableFuture.completedFuture(Collections.singletonList(buildOrderBookView()))); when(queryGateway.query(argThat(this::matchTransactionByIdQuery), any(InstanceResponseType.class))) .thenReturn(CompletableFuture.completedFuture(buildTransactionView())); when(queryGateway.query(argThat(this::matchTransactionsByPortfolioIdQuery), any(MultipleInstancesResponseType.class))) .thenReturn(CompletableFuture.completedFuture(Collections.singletonList(buildTransactionView()))); when(queryGateway.query(argThat(this::matchExecutedTradesByOrderBookIdQuery), any(MultipleInstancesResponseType.class))) .thenReturn(CompletableFuture.completedFuture(Collections.singletonList(buildTradeExecutedView()))); when(queryGateway.query(argThat(this::matchPortfolioByIdQuery), any(InstanceResponseType.class))) .thenReturn(CompletableFuture.completedFuture(buildPortfolioView())); when(queryGateway.query(argThat(this::matchPortfolioByUserIdQuery), any(InstanceResponseType.class))) .thenReturn(CompletableFuture.completedFuture(buildPortfolioView())); when(queryGateway.query(argThat(this::matchUserByIdQuery), any(InstanceResponseType.class))) .thenReturn(CompletableFuture.completedFuture(buildUserView())); when(queryGateway.query(any(FindAllUsersQuery.class), any(MultipleInstancesResponseType.class))) .thenReturn(CompletableFuture.completedFuture(buildAllUsersView())); final QueryController queryController = new QueryController(queryGateway); RestAssuredMockMvc.standaloneSetup(queryController); } private <Q> boolean matchCompanyByIdQuery(Q query) { return query instanceof CompanyByIdQuery && ((CompanyByIdQuery) query).getCompanyId().getIdentifier().equals(COMPANY_ID); } @NotNull private CompanyView buildCompanyView() { CompanyView companyView = new CompanyView(); companyView.setIdentifier(COMPANY_ID); companyView.setName(COMPANY_NAME); companyView.setAmountOfShares(42L); companyView.setValue(1337L); companyView.setTradeStarted(false); return companyView; } private List<CompanyView> buildAllCompaniesView() { return Collections.singletonList(buildCompanyView()); } private <Q> boolean matchOrderBookByIdQuery(Q query) { return query instanceof OrderBookByIdQuery && ((OrderBookByIdQuery) query).getOrderBookId().getIdentifier().equals(ORDER_BOOK_ID); } @NotNull private OrderBookView buildOrderBookView() { OrderBookView orderBookView = new OrderBookView(); orderBookView.setIdentifier(ORDER_BOOK_ID); orderBookView.setCompanyName(COMPANY_NAME); orderBookView.setCompanyIdentifier(COMPANY_ID); orderBookView.setBuyOrders(Collections.singletonList(buildBuyOrder())); orderBookView.setSellOrders(Collections.singletonList(buildSellOrder())); return orderBookView; } @NotNull private OrderView buildBuyOrder() { OrderView buyOrder = new OrderView(); buyOrder.setJpaId(1L); buyOrder.setIdentifier(BUY_ORDER_ID); buyOrder.setUserId(USER_ID); buyOrder.setItemPrice(50L); buyOrder.setItemsRemaining(10L); buyOrder.setType("Buy"); buyOrder.setTradeCount(5L); return buyOrder; } @NotNull private OrderView buildSellOrder() { OrderView sellOrder = new OrderView(); sellOrder.setJpaId(2L); sellOrder.setIdentifier(SELL_ORDER_ID); sellOrder.setUserId(USER_ID); sellOrder.setItemPrice(75L); sellOrder.setItemsRemaining(20L); sellOrder.setType("Sell"); sellOrder.setTradeCount(5L); return sellOrder; } private <Q> boolean matchOrderBooksByCompanyIdQuery(Q query) { return query instanceof OrderBooksByCompanyIdQuery && ((OrderBooksByCompanyIdQuery) query).getCompanyId().getIdentifier().equals(COMPANY_ID); } @NotNull private TransactionView buildTransactionView() { TransactionView transactionView = new TransactionView(); transactionView.setIdentifier(TRANSACTION_ID); transactionView.setOrderBookId(ORDER_BOOK_ID); transactionView.setPortfolioId(PORTFOLIO_ID); transactionView.setCompanyName(COMPANY_NAME); transactionView.setType(TransactionType.BUY); transactionView.setState(TransactionState.CONFIRMED); transactionView.setAmountOfItems(50L); transactionView.setAmountOfExecutedItems(25L); transactionView.setPricePerItem(123L); return transactionView; } private <Q> boolean matchTransactionByIdQuery(Q query) { return query instanceof TransactionByIdQuery && ((TransactionByIdQuery) query).getTransactionId().getIdentifier().equals(TRANSACTION_ID); } private <Q> boolean matchTransactionsByPortfolioIdQuery(Q query) { return query instanceof TransactionsByPortfolioIdQuery && ((TransactionsByPortfolioIdQuery) query).getPortfolioId().getIdentifier().equals(PORTFOLIO_ID); } @NotNull private TradeExecutedView buildTradeExecutedView() { TradeExecutedView tradeExecutedView = new TradeExecutedView(); tradeExecutedView.setGeneratedId(1L); tradeExecutedView.setOrderBookId(ORDER_BOOK_ID); tradeExecutedView.setCompanyName(COMPANY_NAME); tradeExecutedView.setTradeCount(30L); tradeExecutedView.setTradePrice(180L); return tradeExecutedView; } private <Q> boolean matchExecutedTradesByOrderBookIdQuery(Q query) { return query instanceof ExecutedTradesByOrderBookIdQuery && ((ExecutedTradesByOrderBookIdQuery) query).getOrderBookId().getIdentifier().equals(ORDER_BOOK_ID); } @NotNull private PortfolioView buildPortfolioView() { PortfolioView portfolioView = new PortfolioView(); portfolioView.setIdentifier(PORTFOLIO_ID); portfolioView.setUserId(USER_ID); portfolioView.setAmountOfMoney(1_000_000L); portfolioView.setReservedAmountOfMoney(5000L); portfolioView.addItemInPossession(buildItemInPossession()); portfolioView.addReservedItem(buildReservedItem()); return portfolioView; } @NotNull private ItemEntry buildItemInPossession() { ItemEntry itemEntry = new ItemEntry(); itemEntry.setGeneratedId(1L); itemEntry.setCompanyId(COMPANY_ID); itemEntry.setCompanyName(COMPANY_NAME); itemEntry.setIdentifier(ORDER_BOOK_ID); itemEntry.setAmount(321L); return itemEntry; } @NotNull private ItemEntry buildReservedItem() { ItemEntry itemEntry = new ItemEntry(); itemEntry.setGeneratedId(2L); itemEntry.setCompanyId(COMPANY_ID); itemEntry.setCompanyName(COMPANY_NAME); itemEntry.setIdentifier(ORDER_BOOK_ID); itemEntry.setAmount(654L); return itemEntry; } private <Q> boolean matchPortfolioByIdQuery(Q query) { return query instanceof PortfolioByIdQuery && ((PortfolioByIdQuery) query).getPortfolioId().getIdentifier().equals(PORTFOLIO_ID); } private <Q> boolean matchPortfolioByUserIdQuery(Q query) { return query instanceof PortfolioByUserIdQuery && ((PortfolioByUserIdQuery) query).getUserId().getIdentifier().equals(USER_ID); } @NotNull private UserView buildUserView() { UserView userView = new UserView(); userView.setIdentifier(USER_ID); userView.setName(USER_NAME); userView.setUsername("john.doe"); return userView; } private <Q> boolean matchUserByIdQuery(Q query) { return query instanceof UserByIdQuery && ((UserByIdQuery) query).getUserId().getIdentifier().equals(USER_ID); } @NotNull private List<UserView> buildAllUsersView() { return Collections.singletonList(buildUserView()); } }