단순 메시지 수 확인을 넘어서
기본적인 메시지 수 검증으로는 부족할 때가 많습니다. 특정 조건을 만족하는 메시지만 처리됐는지, 올바른 헤더가 설정됐는지, 처리 순서가 맞는지 등을 검증해야 합니다.
메시지 내용 상세 검증
Mock 엔드포인트는 받은 모든 Exchange를 기록합니다. 이를 활용해 세밀한 검증이 가능합니다.
@Test
public void testMessageContent() throws Exception {
MockEndpoint mock = getMockEndpoint("mock:result");
mock.expectedMessageCount(1);
// 바디 검증
mock.message(0).body().isInstanceOf(Order.class);
mock.message(0).body(Order.class).getAmount().isGreaterThan(1000);
// 헤더 검증
mock.message(0).header("status").isEqualTo("APPROVED");
mock.message(0).header(Exchange.HTTP_RESPONSE_CODE).isEqualTo(200);
template.sendBodyAndHeader("direct:orders", new Order(5000), "priority", "HIGH");
mock.assertIsSatisfied();
}
비동기 처리 검증과 타임아웃
비동기 처리는 언제 완료될지 예측하기 어렵습니다. Mock 엔드포인트의 타임아웃과 대기 기능을 활용합니다.
@Test
public void testAsyncProcessing() throws Exception {
MockEndpoint mock = getMockEndpoint("mock:async-result");
mock.expectedMessageCount(5);
mock.setResultWaitTime(10000); // 최대 10초 대기
// 비동기로 메시지 전송
for (int i = 0; i < 5; i++) {
template.asyncSendBody("direct:async", "메시지" + i);
}
// 비동기 처리 완료까지 대기
mock.assertIsSatisfied();
}
메시지 순서 검증
멀티스레드 환경에서 메시지 처리 순서가 보장되어야 할 때 순서 검증이 필요합니다.
@Test
public void testMessageOrdering() throws Exception {
MockEndpoint mock = getMockEndpoint("mock:ordered");
mock.expectedBodiesReceived("first", "second", "third");
// 순서가 반드시 일치해야 함
// 또는 순서 무관하게 포함 여부만 검증
mock.expectedBodiesReceivedInAnyOrder("first", "second", "third");
template.sendBody("direct:start", "first");
template.sendBody("direct:start", "second");
template.sendBody("direct:start", "third");
mock.assertIsSatisfied();
}
에러 경로 테스트
정상 경로만큼 예외 처리 경로도 테스트해야 합니다. 의도적으로 예외를 발생시켜 에러 핸들러가 올바르게 동작하는지 확인합니다.
@Test
public void testErrorHandling() throws Exception {
MockEndpoint errorMock = getMockEndpoint("mock:error");
errorMock.expectedMessageCount(1);
// 예외를 발생시키는 프로세서
context.getRouteDefinition("order-route")
.adviceWith(context, new AdviceWithRouteBuilder() {
@Override
public void configure() {
weaveAddFirst().process(exchange -> {
throw new RuntimeException("의도적 실패");
});
}
});
template.sendBody("direct:orders", "테스트주문");
errorMock.assertIsSatisfied();
}
테스트 자동화 팁
- DataBuilder 패턴: 테스트용 도메인 객체 생성 로직을 별도 클래스로 분리
- 공통 베이스 클래스: 반복되는 설정을 CamelTestSupport를 상속한 공통 클래스에 모으기
- Awaitility: 비동기 조건 대기를 위한 라이브러리, Mock보다 유연한 검증