@Test public void testInterceptMessageConstruction() throws Exception { MessageConstructionInterceptor interceptor = new AbstractMessageConstructionInterceptor() { @Override public boolean supportsMessageType(String messageType) { return MessageType.XML.toString().equalsIgnoreCase(messageType); } @Override protected Message interceptMessage( Message message, String messageType, TestContext context) { return new DefaultMessage("Intercepted!"); } @Override protected String getName() { return "MockInterceptor"; } }; Message in = new DefaultMessage("Hello Citrus!"); Message intercepted = interceptor.interceptMessageConstruction(in, MessageType.XML.toString(), context); Assert.assertEquals(intercepted.getPayload(String.class), "Intercepted!"); intercepted = interceptor.interceptMessageConstruction(in, MessageType.PLAINTEXT.toString(), context); Assert.assertEquals(intercepted.getPayload(String.class), "Hello Citrus!"); }
@Override public void doExecute(TestContext context) { try { Message receivedMessage; Consumer consumer = getOrCreateEndpoint(context).createConsumer(); if (StringUtils.hasText(messageSelector) && consumer instanceof SelectiveConsumer) { receivedMessage = ((SelectiveConsumer) consumer).receive(messageSelector, context, timeout); } else { receivedMessage = consumer.receive(context, timeout); } if (receivedMessage != null) { if (log.isDebugEnabled()) { log.debug("Received message: " + receivedMessage.getPayload()); } throw new CitrusRuntimeException( "Message timeout validation failed! " + "Received message while waiting for timeout on destination"); } } catch (ActionTimeoutException e) { log.info("No messages received on destination. Message timeout validation OK!"); log.info(e.getMessage()); } }
/** * Test for handler routing without Xpath given (implementation takes the value of first node). */ @Test public void testRouteMessageWithDefaultXpath() throws Exception { XPathPayloadMappingKeyExtractor mappingNameExtractor = new XPathPayloadMappingKeyExtractor(); endpointAdapter.setMappingKeyExtractor(mappingNameExtractor); Message response = endpointAdapter.handleMessage(new DefaultMessage("<FooBarTest></FooBarTest>")); Assert.assertEquals(response.getPayload(String.class).trim(), "<FooBarTest>OK</FooBarTest>"); }
/** * Invokes the endpoint adapter with constructed mail message and headers. * * @param request */ protected Message invokeEndpointAdapter(Message request) { MailMessage mailMessage = (MailMessage) request.getPayload(); if (splitMultipart) { return split(mailMessage.getBody(), request.copyHeaders()); } else { StringResult result = new StringResult(); marshaller.marshal(mailMessage, result); return getEndpointAdapter() .handleMessage(new DefaultMessage(result.toString(), request.copyHeaders())); } }
@Override protected Map<String, Object> buildMessageHeaders(TestContext context) { Map<String, Object> headers = super.buildMessageHeaders(context); headers.putAll(message.copyHeaders()); return headers; }
@Override public void validateMessagePayload( Message receivedMessage, Message controlMessage, XmlMessageValidationContext validationContext, TestContext context) throws ValidationException { log.info("Start XML message validation"); try { if (validationContext.isSchemaValidationEnabled()) { validateXMLSchema(receivedMessage, validationContext); validateDTD(validationContext.getDTDResource(), receivedMessage); } validateNamespaces(validationContext.getControlNamespaces(), receivedMessage); validateMessageContent(receivedMessage, controlMessage, validationContext, context); if (controlMessage != null) { Assert.isTrue( controlMessage.getHeaderData().size() <= receivedMessage.getHeaderData().size(), "Failed to validate header data XML fragments - found " + receivedMessage.getHeaderData().size() + " header fragments, expected " + controlMessage.getHeaderData().size()); for (int i = 0; i < controlMessage.getHeaderData().size(); i++) { validateXmlHeaderFragment( receivedMessage.getHeaderData().get(i), controlMessage.getHeaderData().get(i), validationContext, context); } } log.info("XML message validation successful: All values OK"); } catch (ClassCastException e) { throw new CitrusRuntimeException(e); } catch (DOMException e) { throw new CitrusRuntimeException(e); } catch (LSException e) { throw new CitrusRuntimeException(e); } catch (IllegalArgumentException e) { log.error( "Failed to validate:\n" + XMLUtils.prettyPrint(receivedMessage.getPayload(String.class))); throw new ValidationException("Validation failed:", e); } catch (ValidationException ex) { log.error( "Failed to validate:\n" + XMLUtils.prettyPrint(receivedMessage.getPayload(String.class))); throw ex; } }
@Test public void testHandleMessage() { StaticResponseEndpointAdapter endpointAdapter = new StaticResponseEndpointAdapter(); Map<String, Object> header = new HashMap<String, Object>(); header.put("Operation", "UnitTest"); endpointAdapter.setMessageHeader(header); endpointAdapter.setMessagePayload("<TestMessage>Hello User!</TestMessage>"); Message response = endpointAdapter.handleMessage( new DefaultMessage("<TestMessage>Hello World!</TestMessage>")); Assert.assertEquals(response.getPayload(), "<TestMessage>Hello User!</TestMessage>"); Assert.assertNotNull(response.getHeader("Operation")); Assert.assertEquals(response.getHeader("Operation"), "UnitTest"); }
/** Test for handler routing by node content */ @Test public void testRouteMessageByElementTextContent() throws Exception { XPathPayloadMappingKeyExtractor mappingNameExtractor = new XPathPayloadMappingKeyExtractor(); mappingNameExtractor.setXpathExpression("//Test/@name"); endpointAdapter.setMappingKeyExtractor(mappingNameExtractor); Message response = endpointAdapter.handleMessage(new DefaultMessage("<Test name=\"FooTest\"></Test>")); Assert.assertEquals( response.getPayload(String.class).trim(), "<Test name=\"FooTest\">OK</Test>"); response = endpointAdapter.handleMessage(new DefaultMessage("<Test name=\"BarTest\"></Test>")); Assert.assertEquals( response.getPayload(String.class).trim(), "<Test name=\"BarTest\">OK</Test>"); }
/** * Informs message listeners if present that new outbound message is about to be sent. * * @param message */ public void onOutboundMessage(Message message) { if (messageListeners != null && !messageListeners.isEmpty()) { messageListeners.onOutboundMessage(message, this); } else { if (log.isDebugEnabled()) { log.debug("Sent message:" + System.getProperty("line.separator") + message.toString()); } } }
/** * Informs message listeners if present that inbound message was received. * * @param receivedMessage */ public void onInboundMessage(Message receivedMessage) { if (messageListeners != null && !messageListeners.isEmpty()) { messageListeners.onInboundMessage(receivedMessage, this); } else { if (log.isDebugEnabled()) { log.debug( "Received message:" + System.getProperty("line.separator") + (receivedMessage != null ? receivedMessage.toString() : "")); } } }
@Override public boolean accept(String from, String recipient) { if (autoAccept) { return true; } StringResult result = new StringResult(); marshaller.marshal(createAcceptRequest(from, recipient), result); Message response = getEndpointAdapter().handleMessage(new DefaultMessage(result.toString())); if (response == null || response.getPayload() == null) { throw new CitrusRuntimeException( "Did not receive accept response. Missing accept response because autoAccept is disabled."); } AcceptResponse acceptResponse = null; if (response.getPayload() instanceof AcceptResponse) { acceptResponse = (AcceptResponse) response.getPayload(); } else if (response.getPayload() instanceof String) { acceptResponse = (AcceptResponse) marshaller.unmarshal(response.getPayload(Source.class)); } if (acceptResponse == null) { throw new CitrusRuntimeException("Unable to read accept response from payload: " + response); } return acceptResponse.isAccept(); }
@Test public void testSendBuilderWithObjectMessageInstance() { final Message message = new DefaultMessage(new Integer(10)).setHeader("operation", "foo"); MockTestDesigner builder = new MockTestDesigner(applicationContext) { @Override public void configure() { send(messageEndpoint).message(message); } }; builder.configure(); TestCase test = builder.getTestCase(); Assert.assertEquals(test.getActionCount(), 1); Assert.assertEquals(test.getActions().get(0).getClass(), SendMessageAction.class); SendMessageAction action = ((SendMessageAction) test.getActions().get(0)); Assert.assertEquals(action.getName(), "send"); Assert.assertEquals(action.getEndpoint(), messageEndpoint); Assert.assertEquals(action.getMessageBuilder().getClass(), StaticMessageContentBuilder.class); StaticMessageContentBuilder messageBuilder = (StaticMessageContentBuilder) action.getMessageBuilder(); Assert.assertEquals(messageBuilder.getMessage().getPayload(), 10); Assert.assertEquals(messageBuilder.getMessageHeaders().size(), 0L); Assert.assertEquals( messageBuilder.getMessage().copyHeaders().size(), message.copyHeaders().size()); Assert.assertEquals( messageBuilder.getMessage().getHeader(MessageHeaders.ID), message.getHeader(MessageHeaders.ID)); Assert.assertEquals(messageBuilder.getMessage().getHeader("operation"), "foo"); Message constructed = messageBuilder.buildMessageContent(new TestContext(), MessageType.PLAINTEXT.name()); Assert.assertEquals(constructed.copyHeaders().size(), message.copyHeaders().size()); Assert.assertEquals(constructed.getHeader("operation"), "foo"); Assert.assertEquals( constructed.getHeader(MessageHeaders.ID), message.getHeader(MessageHeaders.ID)); }
/** * Validate message payloads by comparing to a control message. * * @param receivedMessage * @param validationContext * @param context */ protected void validateMessageContent( Message receivedMessage, Message controlMessage, XmlMessageValidationContext validationContext, TestContext context) { if (controlMessage == null || controlMessage.getPayload() == null) { log.info("Skip message payload validation as no control message was defined"); return; } if (!(controlMessage.getPayload() instanceof String)) { throw new IllegalArgumentException( "DomXmlMessageValidator does only support message payload of type String, " + "but was " + controlMessage.getPayload().getClass()); } String controlMessagePayload = controlMessage.getPayload(String.class); if (receivedMessage.getPayload() == null || !StringUtils.hasText(receivedMessage.getPayload(String.class))) { Assert.isTrue( !StringUtils.hasText(controlMessagePayload), "Unable to validate message payload - received message payload was empty, control message payload is not"); return; } else if (!StringUtils.hasText(controlMessagePayload)) { return; } log.info("Start XML tree validation ..."); Document received = XMLUtils.parseMessagePayload(receivedMessage.getPayload(String.class)); Document source = XMLUtils.parseMessagePayload(controlMessagePayload); XMLUtils.stripWhitespaceNodes(received); XMLUtils.stripWhitespaceNodes(source); if (log.isDebugEnabled()) { log.debug("Received message:\n" + XMLUtils.serialize(received)); log.debug("Control message:\n" + XMLUtils.serialize(source)); } validateXmlTree( received, source, validationContext, namespaceContextBuilder.buildContext(receivedMessage, validationContext.getNamespaces()), context); }
@Override public void deliver(String from, String recipient, InputStream data) { try { MimeMailMessage mimeMailMessage = new MimeMailMessage(new MimeMessage(getSession(), data)); Message request = messageConverter.convertInbound(mimeMailMessage, getEndpointConfiguration()); Message response = invokeEndpointAdapter(request); if (response != null && response.getPayload() != null) { MailResponse mailResponse = null; if (response.getPayload() instanceof MailResponse) { mailResponse = (MailResponse) response.getPayload(); } else if (response.getPayload() instanceof String) { mailResponse = (MailResponse) marshaller.unmarshal(response.getPayload(Source.class)); } if (mailResponse != null && mailResponse.getCode() != MailResponse.OK_CODE) { throw new RejectException(mailResponse.getCode(), mailResponse.getMessage()); } } } catch (MessagingException e) { throw new CitrusRuntimeException(e); } }
@Override protected Object buildMessagePayload(TestContext context) { return message.getPayload(); }
/** * Validate message with a XML schema. * * @param receivedMessage * @param validationContext */ protected void validateXMLSchema( Message receivedMessage, XmlMessageValidationContext validationContext) { if (receivedMessage.getPayload() == null || !StringUtils.hasText(receivedMessage.getPayload(String.class))) { return; } try { Document doc = XMLUtils.parseMessagePayload(receivedMessage.getPayload(String.class)); if (!StringUtils.hasText(doc.getFirstChild().getNamespaceURI())) { return; } log.info("Starting XML schema validation ..."); XmlValidator validator = null; XsdSchemaRepository schemaRepository = null; if (validationContext.getSchema() != null) { validator = applicationContext .getBean(validationContext.getSchema(), XsdSchema.class) .createValidator(); } else if (validationContext.getSchemaRepository() != null) { schemaRepository = applicationContext.getBean( validationContext.getSchemaRepository(), XsdSchemaRepository.class); } else if (schemaRepositories.size() == 1) { schemaRepository = schemaRepositories.get(0); } else if (schemaRepositories.size() > 0) { for (XsdSchemaRepository repository : schemaRepositories) { if (repository.canValidate(doc)) { schemaRepository = repository; } } if (schemaRepository == null) { throw new CitrusRuntimeException( String.format( "Failed to find proper schema repository in Spring bean context for validating element '%s(%s)'", doc.getFirstChild().getLocalName(), doc.getFirstChild().getNamespaceURI())); } } else { log.warn( "Neither schema instance nor schema repository defined - skipping XML schema validation"); return; } if (schemaRepository != null) { if (!schemaRepository.canValidate(doc)) { throw new CitrusRuntimeException( String.format( "Unable to find proper XML schema definition for element '%s(%s)' in schema repository '%s'", doc.getFirstChild().getLocalName(), doc.getFirstChild().getNamespaceURI(), schemaRepository.getName())); } List<Resource> schemas = new ArrayList<>(); for (XsdSchema xsdSchema : schemaRepository.getSchemas()) { if (xsdSchema instanceof XsdSchemaCollection) { for (Resource resource : ((XsdSchemaCollection) xsdSchema).getSchemaResources()) { schemas.add(resource); } } else if (xsdSchema instanceof WsdlXsdSchema) { for (Resource resource : ((WsdlXsdSchema) xsdSchema).getSchemaResources()) { schemas.add(resource); } } else { synchronized (transformerFactory) { ByteArrayOutputStream bos = new ByteArrayOutputStream(); try { transformerFactory .newTransformer() .transform(xsdSchema.getSource(), new StreamResult(bos)); } catch (TransformerException e) { throw new CitrusRuntimeException( "Failed to read schema " + xsdSchema.getTargetNamespace(), e); } schemas.add(new ByteArrayResource(bos.toByteArray())); } } } validator = XmlValidatorFactory.createValidator( schemas.toArray(new Resource[schemas.size()]), WsdlXsdSchema.W3C_XML_SCHEMA_NS_URI); } SAXParseException[] results = validator.validate(new DOMSource(doc)); if (results.length == 0) { log.info("Schema of received XML validated OK"); } else { log.error( "Schema validation failed for message:\n" + XMLUtils.prettyPrint(receivedMessage.getPayload(String.class))); // Report all parsing errors log.debug("Found " + results.length + " schema validation errors"); StringBuilder errors = new StringBuilder(); for (SAXParseException e : results) { errors.append(e.toString()); errors.append("\n"); } log.debug(errors.toString()); throw new ValidationException("Schema validation failed:", results[0]); } } catch (IOException e) { throw new CitrusRuntimeException(e); } catch (SAXException e) { throw new CitrusRuntimeException(e); } }
/** * Validate namespaces in message. The method compares namespace declarations in the root element * of the received message to expected namespaces. Prefixes are important too, so differing * namespace prefixes will fail the validation. * * @param expectedNamespaces * @param receivedMessage */ protected void validateNamespaces( Map<String, String> expectedNamespaces, Message receivedMessage) { if (CollectionUtils.isEmpty(expectedNamespaces)) { return; } if (receivedMessage.getPayload() == null || !StringUtils.hasText(receivedMessage.getPayload(String.class))) { throw new ValidationException( "Unable to validate message namespaces - receive message payload was empty"); } log.info("Start XML namespace validation"); Document received = XMLUtils.parseMessagePayload(receivedMessage.getPayload(String.class)); Map<String, String> foundNamespaces = XMLUtils.lookupNamespaces(receivedMessage.getPayload(String.class)); if (foundNamespaces.size() != expectedNamespaces.size()) { throw new ValidationException( "Number of namespace declarations not equal for node " + XMLUtils.getNodesPathName(received.getFirstChild()) + " found " + foundNamespaces.size() + " expected " + expectedNamespaces.size()); } for (Entry<String, String> entry : expectedNamespaces.entrySet()) { String namespace = entry.getKey(); String url = entry.getValue(); if (foundNamespaces.containsKey(namespace)) { if (!foundNamespaces.get(namespace).equals(url)) { throw new ValidationException( "Namespace '" + namespace + "' values not equal: found '" + foundNamespaces.get(namespace) + "' expected '" + url + "' in reference node " + XMLUtils.getNodesPathName(received.getFirstChild())); } else { log.info( "Validating namespace " + namespace + " value as expected " + url + " - value OK"); } } else { throw new ValidationException( "Missing namespace " + namespace + "(" + url + ") in node " + XMLUtils.getNodesPathName(received.getFirstChild())); } } log.info("XML namespace validation finished successfully: All values OK"); }