package camelinaction; import com.consol.citrus.actions.AbstractTestAction; import com.consol.citrus.annotations.CitrusTest; import com.consol.citrus.condition.AbstractCondition; import com.consol.citrus.context.TestContext; import com.consol.citrus.dsl.junit.JUnit4CitrusTestDesigner; import com.consol.citrus.exceptions.CitrusRuntimeException; import com.consol.citrus.http.client.HttpClient; import com.consol.citrus.jms.endpoint.JmsEndpoint; import com.consol.citrus.jms.message.JmsMessageHeaders; import org.apache.camel.spring.SpringCamelContext; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.test.context.ContextConfiguration; /** * Citrus Integration test that test a Camel application. * We use Citrus as a HTTP client to send a message to a Camel application * that routes the messages to a JMS queue, which Citrus is simulating and * returning a reply message on the JMS reply queue, which Camel receives * and routes back to the calling HTTP client. * <p/> * In other words we have Citrus simulating a JMS backend, and as a client as well. * Notice how we can setup the test using the citrus designer. */ @ContextConfiguration(classes = EndpointConfig.class) public class CitrusIT extends JUnit4CitrusTestDesigner { @Autowired private HttpClient statusHttpClient; @Autowired private JmsEndpoint statusEndpoint; @Autowired @SuppressWarnings("SpringJavaAutowiringInspection") private SpringCamelContext orderService; @Test @CitrusTest public void orderStatus() throws Exception { description("Checking order should be on hold"); // random 5 digit order number variable("orderId", "citrus:randomNumber(5)"); // the HTTP client is sending the order http().client(statusHttpClient) .send() .get("/status?id=${orderId}") .contentType("text/xml").accept("text/xml") // use fork so we can continue with the test design (otherwise this would be a synchronous call) .fork(true); echo("Sent HTTP Request with orderId: ${orderId}"); // the Camel application will call a JMS backend so lets use Citrus to simulate this // on the JMS queue we expect to receive the following message // and capture the JMS correlation ID so we can send back the correct reply message receive(statusEndpoint) .payload("<order><id>${orderId}</id></order>") .extractFromHeader(JmsMessageHeaders.CORRELATION_ID, "cid"); // send back the JMS reply message that the order is done // and with the correct JMSCorrelationID send(statusEndpoint) .payload("<order><id>${orderId}</id><status>ON HOLD</status></order>") .header(JmsMessageHeaders.CORRELATION_ID, "${cid}"); // the HTTP client is expected to receive a 200 OK message with the following XML structure http().client(statusHttpClient) .receive() .response(HttpStatus.OK) .payload("<order><id>${orderId}</id><status>ON HOLD</status></order>") .contentType("text/xml"); // wait for Camel to shutdown nicely (citrus should have this out of the box in citrus-camel) stopAndWaitForGracefulShutdown(); } /** * Stop and wait for graceful shutdown of Camel context before closing the test. */ private void stopAndWaitForGracefulShutdown() { // stop the Camel context with custom test action. action(new AbstractTestAction() { @Override public void doExecute(TestContext context) { try { orderService.stop(); } catch (Exception e) { throw new CitrusRuntimeException("Failed to stop Camel context"); } } }); waitFor().condition(new AbstractCondition() { @Override public boolean isSatisfied(TestContext context) { return orderService.isStopped(); } @Override public String getSuccessMessage(TestContext context) { return "Successfully stopped Camel context"; } @Override public String getErrorMessage(TestContext context) { return "Failed to stop Camel context"; } }); } }