OrderRepository
상호 작용 유형 | 컨슈머 | 프로바이더 | 계약 |
---|---|---|---|
REST 요청/응답 | API 게이트웨이 | 주문 서비스 | http 요청/응답 |
발행/구독 | 주문 이력 서비스 | 주문 서비스 | 도메인 이벤트 |
비동기 요청/응답 | 주문 서비스 | 주방 서비스 | 커맨드 메시지 및 응답 메시지 |
HttpTest
라는 테스트 클래스를 생성
HttpTest
- Rest Assured 목 MVC로 프로바이더(주문 서비스) 컨트롤러를 테스트하는 클래스BaseHttp
라는 기초 클래스가 목 디펜던시가 주입된 OrderController
생성 후 스프링 MVC를 구성org.springframework.cloud.contract.spec.Contract.make {
request {
method 'GET'
url '/orders/1223232'
}
response {
status 200
headers {
header('Content-type': 'application/json;charset=UTF-8')
}
body(```{"orderId" : "1223232", "state" : "APPROVAL_PENDING"}```)
}
}
HttpBase
public abstract class HttpBase {
private StandaloneMockMvcBuilder controllers(Object ... controllers) {
...
return MockMvcBuilders.standaloneSetUp(controllers)
.setMessageConverters(...);
}
@Before
public void setup() {
OrderService orderService = mock(OrderService.class);
orderRepository orderRepository = mock(OrderRepository.class);
OrderController orderController = new OrderController(orderSercice, orderRepository);
when(orderRepository.findById(OrderDetailsMother.ORDER_ID))
.thenReturn(Optional.of(OrderDetailsMother.CHICKEN_VINDALOO_ORDER));
...
}
}
OrderServiceProxy
는 GET /orders/{orderId}를 호출@RunWith(SpringRunner.class)
@SpringBootTest(classes=TestConfiguration.class,
webEnvironment=SpringBootTest.WebEnvironment.NONE)
@AutoConfigureStupRunner(ids = // 스프링 클라우드 컨트랙트가 주문 서비스 계약대로 와이어목을 구성
{"net.chrisrichardson.ftgo.contract:ftgo-order-service-contracts"}
)
@DirtiesContext
public class OrderServiceProxyIntegrationTest {
@Value("${stubrunner.runningstubs.ftgo-order-service-contracts.port}") // 와이어목이 실행 중인 랜덤 포트 획득
private int port;
private OrderDestinations orderDestinations;
private OrderServiceProxy orderService;
@Before
public void setUp() throws Exception {
orderDestinations = new OrderDestinations();
orderDestinations.setOrderServiceUrl("http://localhost:" + port);
orderService = new OrderServiceProxy(orderDestinations, WebClient.create());
}
@Test
public void shouldVerifyExistingCustomer() {
OrderInfo result = orderService.findOrderById("1223232").block();
assertEquals("1223232", result.getOrderId());
assertEquals("APPROVAL_PENDING", result.getState());
}
...
}
MessagingBase
를 상속한 테스트 클래스를 코드-생성MessagingBase
의 훅 메서드를 호출하면 이벤트 발행이 트리거 된다.package contracts;
org.springframework.cloud.contract.spec.Contract.make {
label 'orderCreatedEvent' // 이벤트 발행을 트리거하는 컨슈머 테스트에서 사용
input {
triggeredBy('orderCreated()') // 코드-생성된 프로바이더 테스트에 의해 호출
}
outputMessage { // OrderCreated 도메인 이벤트
sendTo('net.chrisrichardson.ftgo.orderservice.domain.Order')
body(```{"orderDetails":{"lineItems":[{"quantity":5, "menuItemId":"1", ...}]}}```)
headers {
header('event-aggregate-type',
'net.chrisrichardson.ftgo.orderservice.domain.Order')
...
}
}
}
Messagingbase
이다.@RunWith(SpringRunner.class)
@SpringBootTest(classes = MessagingBase.TestConfiguration.class,
webEnvironment = SpringBootTest.WebEnvironment.NONE)
@AutoConfigureMessageVerifier
public abstract class MessagingBase {
@Configuration
@EnableAutoConfiguration
@Import({
EventuateContractVerifierConfiguration.class
TramEventsPublisherConfiguration.class,
TramInMemoryConfiguration.class})
public static class TestConfiguration {
@Bean
public OrderDomainEventPublisher orderAggregateEventPublisher(
DomainEventPublisher eventPublisher) {
return new OrderDomainEventPublisher(eventPublisher);
}
}
@Autoworied
private OrderDomainEventPublisher orderAggregateEventPublisher;
protected void orderCreated() { // 코드-생성된 테스트 하위 클래스는 orderCreated()를 호출하여 이벤트를 발행
orderAggregateEventPublisher.publish(CHCKEN_VINDALOO_ORDER,
Collections.singletonList(new OrderCreatedEvent(...)));
}
}
OrderDomainEventPublisher
가 인-메모리 메시징 스텁을 사용하도록 구성orderCreated()
메서드는 계약으로 생성된 테스트 메서드가 호출
OrderHistoryEventHandlers
OrderHistoryDao
가 주입된 OrderHistoryEventHandlers
를 생성한다.@RunWith(SpringRunner.class)
@SpringBootTest(classes = OrderHistoryEventHandlerTest.TestConfiguration.class,
webEnvironment=SpringBootTest.WebEnvironment.NONE)
@AutoConfigureStubRunner(ids =
{"net.chrisrichadson.ftgo.contracts:ftgo-order-service-contracts"}
)
@DirtiesContext
public class OrderHistoryHandlersTest {
@Configuration
@EnableAutoConfiguration
@Import({
OrderHistoryServiceMessagingConfiguration.class,
TramCommandProducerConfiguration.class,
TramInMemoryConfiguration.class,
EventuateContractVerifierConfiguration.class
})
public static class TestConfiguration {
@Bean
public ChannelMapping channelMapping() {
return new DefaultChannelMapping.DefaultChannelMappingBuilder().build();
}
@Bean
public OrderHistoryDao orderHistoryDao() {
return mock(OrderHistoryDao.class);
}
}
@Test
public void shouldHandleOrderCreatedEvent() throws ... {
...
stubFinder.trigger("orderCreatedEvent"); // orderCreatedEvent 스텁을 트리거하여 이벤트 발행
eventually(() -> // 이벤트를 잘 소비했는지 검증
...
)
}
}