I have written unit test cases to test the message processors individually in my mule flow.
But the unit test fails with error
org.mule.api.transformer.TransformerMessagingException: Property "xsl-file or xsl-text" not set.
One or more of them must be set (org.mule.api.lifecycle.InitialisationException).
Message payload is of type: String
(org.mule.api.transformer.TransformerMessagingException). Message payload is of type: String
One of the transformers is an XSLT as shown below.
<mule-xml:xslt-transformer maxIdleTransformers="2" maxActiveTransformers="5" xsl-file="C:\EWS\myproj\src\main\resources\xslt\DataAdder.xsl"
name="AdderXSLT" >
</mule-xml:xslt-transformer>
The unit test method looks as below.
MessageProcessor subFlow = muleContext.getRegistry().lookupObject("AdderXSLT");
MuleEvent result = subFlow.process(getTestEvent(getFileAsString("SamplePayloads/input.xml")));
System.out.println("The output from Event is " + result.getMessageAsString());
System.out.println("The converted XML is " + result.getMessage().getPayloadAsString());
assertNotNull(result);
assertNull(result.getMessage().getExceptionPayload());
assertFalse(result.getMessage().getPayload() instanceof NullPayload);
Please help me understand what's going wroong here.
I came across something similar before where you need to initialise the transformer explicitly when you're not executing it within the context of a flow. To test xslt transformers I have used similar to the following is the past:
XsltTransformer xslt = FunctionalTestCase.muleContext.getRegistry()
.lookupObject("SuccessResponseTransformer");
xslt.setReturnDataType(DataType.STRING_DATA_TYPE);
xslt.initialise();
String result = (String) xslt.transform(srcXML);
You could try something like this or try casting to an XsltTransformer to initialise.
I believe this is because when you execute the MP as part of a flow it is part of a MessageProcessorChain that will initialise each MP where appropriate. If you take a look at the following code from AbstractMessageProcessorChain - http://grepcode.com/file/repo1.maven.org/maven2/org.mule/mule-core/3.3.1/org/mule/processor/chain/AbstractMessageProcessorChain.java#AbstractMessageProcessorChain.initialise%28%29 :
public void initialise() throws InitialisationException
{
for (MessageProcessor processor : processors)
{
// MULE-5002 TODO review MP Lifecycle
if (processor instanceof Initialisable /* && !(processor instanceof Transformer) */)
{
((Initialisable) processor).initialise();
}
}
}
Note that (!instanceof Transformer) is commented out. So it will initialise the XsltTransformer for you.
Where as directly referencing the MessageProcessor will not.
Related
I am new to lambda and trying to create a function, where i can consume both SNSEvent and simple json as payload in my requestHandler method. How can i do it in Java? should i take my input as Object type?
public class LogEvent implements RequestHandler<SNSEvent, Object> {
public Object handleRequest(SNSEvent request, Context context){
String timeStamp = new SimpleDateFormat("yyyy-MM-dd_HH:mm:ss").format(Calendar.getInstance().getTime());
context.getLogger().log("Invocation started: " + timeStamp);
context.getLogger().log(request.getRecords().get(0).getSNS().getMessage());
timeStamp = new SimpleDateFormat("yyyy-MM-dd_HH:mm:ss").format(Calendar.getInstance().getTime());
context.getLogger().log("Invocation completed: " + timeStamp);
return null;
}
}
this works fine. but if i want the flexibility of passing simple Json like below
{
"req": "test"
}
from aws console lambda test section. to manually trigger few tests without sending actual SNSEvent Object. how should i modify my code.
Note: above mentioned code and test are not exactly what i have but providing any suggestion on given code itself will be helpful.
I am trying to test the deadLetterChanel in apache camel,
here's the production code snippet (part of my RouterBuilder):
from(dateQueue())
.routeId(ROUTE_DATE)
.to(log(myConsumer))
.transform().body(String.class, it -> myConsumer.consume(LocalDate.parse(it)))
.split(body())
.to(log(myConsumer))
.marshal().json()
.to(processorExchange());
errorHandler(deadLetterChannel(dlqDirect()));
// #formatter:off
from(dlqDirect())
.to("log:dlq")
.choice()
.when(it -> ROUTE_DATE.equals(it.getFromRouteId())).to(dateDLExchange())
// other when expressions here
.end();
// #formatter:on
And here's the test code:
#Test
void testErrorCaseOfDateRoute_ShouldGoToDateDlExchange() throws Exception {
// given:
MockEndpoint dateDLExchangeMock = camelContext.getEndpoint("mock:test", MockEndpoint.class);
AdviceWith.adviceWith(camelContext, ROUTE_DATE,
in -> in.interceptSendToEndpoint(dateDLExchange()).to(dateDLExchangeMock)
);
dateDLExchangeMock.expectedMessageCount(1);
dateDLExchangeMock.expectedBodiesReceived("invalid date");
// when:
producerTemplate.sendBody(dateExchange(), "invalid date");
// then:
dateDLExchangeMock.assertIsSatisfied();
}
The assertion fails!
However, if I changed the mock to intercept dlqDirect() (direct endpoint) instead of dateDLExchange() (rabbitmq endpoint), it works fine, but I want to include the choice() function in my tests as well.
I am doing mini-integration tests using RabbitMQ in TestContainer, so I really think to listen to the queue in rabbitmq instance and assert the message there instead of doing the test using Camel! (Can camel help here?)
It worth noting that when I test this case manullay, I got my invalid message into the rabbitmq date_dl_queue which is bound to date_dl_exchange. ( I mean, it works)
I solved it by using a route-scoped errorHandler, instead of using a generic error handler for all routes and then using when-expressions.
So, the code changed to look like this:
from(dateQueue())
.routeId(ROUTE_DATE)
.errorHandler(buildErrorHandler(dateDLExchange())) // <<< Notice this
.to(log(myConsumer))
.transform().body(String.class, it -> myConsumer.consume(LocalDate.parse(it)))
.split(body())
.to(log(myConsumer))
.marshal().json()
.to(processorExchange());
private DefaultErrorHandlerBuilder buildErrorHandler(String deadLetterUri) {
return deadLetterChannel(deadLetterUri)
.logExhausted(true)
.logHandled(true)
.....
.;
}
I am migrating to maven and Now it has dependency
<!-- https://mvnrepository.com/artifact/com.codepine.api/testrail-api-java-client -->
<dependency>
<groupId>com.codepine.api</groupId>
<artifactId>testrail-api-java-client</artifactId>
<version>2.0.1</version>
</dependency>
I have written the below code to update the result..
TestRail testrail= TestRail.builder("https://mytestrail.domain.com", "username", "password").applicationName("appname").build();
Tests tests = testrail.tests();
java.util.List<com.codepine.api.testrail.model.Test> lst = tests.list(43662).execute();
System.out.println(lst.get(0));
System.out.println(lst.size());
List<ResultField> customResultFields = testrail.resultFields().list().execute();
//HashMap data = new HashMap();
//data.put("comment", "Test Purpose for all");
//customResultFields= (java.util.List<ResultField>) data;
int status=5;
testrail.results().addForCase(43662, 30056283, new Result().setStatusId(status), customResultFields).execute();
I have a list of step details which is extracted from ExtentReport. So basically how to update my own custom message instead of just "This test was marked as 'Failed' or 'Passed'"
By seeing this.. https://www.gurock.com/testrail/docs/user-guide/howto/fields
May be we need to create something on the Field class. But anybody has idea on that would be good to guide that complete that. As I am using automation results.. i dont want each step result.. Just adding as comment entire log and make it pass/fail.
Result has few more options to add like setComment along with Status..
testrail.results().addForCase(43662, 30056283, new Result().setComment("Test Purpose Print as Pass").setStatusId(status), customResultFields).execute();
It will set the comment whatever you are giving and change the status..
You can define a Mapper named Data and put the necessary information in it. You can then add this data as a parameter to the http request.
public static void sendScenarioResults(boolean failed, int runId, int caseId, String errorMessage) {
try {
Map data = new HashMap();
data.put("status_id", failed ? 5 : 1);
data.put("comment", errorMessage);
client.sendPost("add_result_for_case/" + runID + "/" + caseId,
data);
} catch (IOException e) {
e.printStackTrace();
} catch (APIException e) {
e.printStackTrace();
}
}
}
In addition, you can add a lot of information to the data, you can use Testrail Api docs for this.
Testrail Api docs
Based on your testing framework (JUnit of TestNG), try to use one of these libs:
TestRail-JUnit
TestRail-TestNG
Both of them have Medium articles on how to integrate it just in a few steps (see README.md there)
I'm using ph-schematron to validate my XML files. I'm able to validate the files correctly but I couldn't find how to generate reports about failing assertions.
This is my context(point-of-interest):
<bpmn:extensionElements>
<activiti:in sourceExpression="RESERVATION" target="OPERATION_CODE"/>
<activiti:in sourceExpression="true" target="IS_SYNC"/>
</bpmn:extensionElements>
This is my Schematron schema:
<iso:schema
xmlns="http://purl.oclc.org/dsdl/schematron"
xmlns:iso="http://purl.oclc.org/dsdl/schematron"
queryBinding='xslt2'
schemaVersion='ISO19757-3'>
<iso:title>Test ISO schematron file. Introduction mode</iso:title>
<iso:ns prefix='bpmn' uri='http://www.omg.org/spec/BPMN/20100524/MODEL'/>
<iso:ns prefix='activiti' uri='http://activiti.org/bpmn'/>
<iso:let name="callActivity" value="bpmn:definitions/bpmn:process/bpmn:callActivity"/>
<iso:let name="inSourceExpression" value="child::activiti:in/sourceExpression"/>
<iso:let name="outSourceExpression" value="child::activiti:out/sourceExpression"/>
<iso:let name="inTarget" value="child::activiti:in/target"/>
<iso:let name="outTarget" value="child::activiti:out/target"/>
<!-- Your constraints go here -->
<iso:pattern id="RESERVATION">
<iso:p>
This pattern validates call activities with RESERVATION operation code.
</iso:p>
<iso:rule context="$callActivity[bpmn:extensionElements/activiti:in[(#target='OPERATION_CODE') and (#sourceExpression='RESERVATION')]]/bpmn:extensionElements">
<iso:assert test="count(($inSourceExpression='RESERVATION') and ($inTarget='OPERATION_CODE')) = 0">err1</iso:assert>
<iso:assert test="count(($inSourceExpression='true') and ($inTarget='IS_SYNC')) = 1">err2</iso:assert>
</iso:rule>
</iso:pattern>
</iso:schema>
This is my Java code:
public static boolean validateXMLViaPureSchematron(#Nonnull final String aSchematronFilePath, #Nonnull final File aXMLFile) throws Exception {
final SchematronResourcePure schematronResourcePure = SchematronResourcePure.fromClassPath(aSchematronFilePath);
IPSErrorHandler errorHandler = new CollectingPSErrorHandler();
schematronResourcePure.setErrorHandler(errorHandler);
final boolean validSchematron = schematronResourcePure.isValidSchematron();
if (!validSchematron) {
throw new IllegalArgumentException("Invalid Schematron!");
}
final Source streamSource = new StreamSource(aXMLFile);
final EValidity schematronValidity = schematronResourcePure.getSchematronValidity(streamSource);
return schematronValidity.isValid();
}
I can see the result of the validation by calling schematronResourcePure.getSchematronValidity(streamSource) but I want to see (a report would be sufficient) which rules are failed(err1 or err2). I've read about SVRL but I don't know how to generate report.
Thank you.
Simply call applySchematronValidationToSVRL to get the full SVRL (Schematron Validation Result List) document. You can query it for failed asserts or reports.
Code example where only failed asserts are printed:
SchematronOutputType schematronOutputType = schematronResourcePure.applySchematronValidationToSVRL(streamSource);
List<Object> failedAsserts = schematronOutputType.getActivePatternAndFiredRuleAndFailedAssert();
for (Object object : failedAsserts) {
if (object instanceof FailedAssert) {
FailedAssert failedAssert = (FailedAssert) object;
System.out.println(failedAssert.getText());
System.out.println(failedAssert.getTest());
}
}
In my test I check:
assertEquals("<div class=\"action-button\" title=\"actionButton\">"</div>", result);
If someone changes the html (result), putting there SPACE, the HTML still valid, but my test would fail.
Is there some way to compare two html pieces if those are equal as HTML. Like assertHTMLEquals
XML UNIT says that this two lines are equal:
string1:
<ldapConfigurations>
<ldap tenantid="" active="false">
</ldap>
</ldapConfigurations>
string2:
<ldapConfigurations>
<ldapdd tenantid="" active="false">
</ldap>
</ldapConfigurations>
but they are not, as you can see. (see: ldapdd )
This won't necessarily work for your case, but if your HTML happens to be valid XML it will. You can use this tool called xmlunit. With it, you can write an assert method that looks like this:
public static void assertXMLEqual(Reader reader, String xml) {
try {
XMLAssert.assertXMLEqual(reader, new StringReader(xml));
} catch (Exception ex) {
ex.printStackTrace();
XMLAssert.fail();
}
}
If that doesn't work for you, maybe there's some other tool out there meant for HTML comparisons. And if that doesn't work, you may want to end up using a library like jtagsoup (or whatever) and comparing if all the fields it parses are equal.
You can achieve malformed HTML asserting throught the TolerantSaxDocumentBuilder utility of XMLUnit.
TolerantSaxDocumentBuilder tolerantSaxDocumentBuilder =
new TolerantSaxDocumentBuilder(XMLUnit.newTestParser());
HTMLDocumentBuilder htmlDocumentBuilder =
new HTMLDocumentBuilder(tolerantSaxDocumentBuilder);
XMLAssert.assertXMLEqual(htmlDocumentBuilder.parse(expectedHTML),
htmlDocumentBuilder.parse(actualHTML));
To support badly formed HTML (such as elements without closing tags - unthinkable in XML), you must make use of an additional document builder, the TolerantSaxDocumentBuilder, along with the HTMLDocumentBuilder (this one will allow asserting on web pages). After that, assert the documents as usual.
Working code example:
public class TestHTML {
public static void main(String[] args) throws Exception {
String result = "<div class=\"action-button\" title=\"actionButton\"> </div>";
assertHTMLEquals("<div class=\"action-button\" title=\"actionButton\"></div>", result); // ok!
// notice it is badly formed
String expectedHtml = "<html><title>Page Title</title>"
+ "<body><h1>Heads<ul>"
+ "<li id='1'>Some Item<li id='2'>Another item";
String actualMalformedHTML = expectedHtml.replace(" ", " "); // just added some spaces, wont matter
assertHTMLEquals(expectedHtml, actualMalformedHTML); // ok!
actualMalformedHTML = actualMalformedHTML.replace("Heads", "Tails");
assertHTMLEquals(expectedHtml, actualMalformedHTML); // assertion fails
}
public static void assertHTMLEquals(String expectedHTML, String actualHTML) throws Exception {
TolerantSaxDocumentBuilder tolerantSaxDocumentBuilder = new TolerantSaxDocumentBuilder(XMLUnit.newTestParser());
HTMLDocumentBuilder htmlDocumentBuilder = new HTMLDocumentBuilder(tolerantSaxDocumentBuilder);
XMLAssert.assertXMLEqual(htmlDocumentBuilder.parse(expectedHTML), htmlDocumentBuilder.parse(actualHTML));
}
}
Notice that XML functions, such as XPath, will be available to your HTML document as well.
If using Maven, add this to your pom.xml:
<dependency>
<groupId>xmlunit</groupId>
<artifactId>xmlunit</artifactId>
<version>1.4</version>
</dependency>