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)
.....
.;
}
Related
I have a groovy script that loops through each test step, in each test case, in each test suite in the project. Each test case in the project has two custom properties assigned it is, Test_Case_Response_Time and Test_Case_Response_Size. I am trying to get it so that when it loops through each test case it log.info those two custom property for each test case.
Groovy Script:
//Loop thru the suites, followed by cases in each suite
suites.each
{ suite ->
//For each test SUITE perform the following action
//------------------------------------------------
def tSuite = project.getTestSuiteByName(suite)
tSuite.testCaseList.each
{ kase ->
//For each test CASE perform the following action
//-----------------------------------------------
kase.testStepList.each
{
//For each test step perform the following action
//-----------------------------------------------
if(it.metaClass.hasProperty(it,'assertionStatus')){
def assertions = it.getAssertionList()
assertions.each
{ assertion ->
if(it.assertionStatus == AssertionStatus.VALID)
{
PassedTestCase += 1
}
else if(it.assertionStatus == AssertionStatus.FAILED)
{
FailedTestCase += 1
}
}
}
//-----------------------------------------------
}
log.info testRunner.testCase["Test_Case_00: Setup"].getPropertyValue("Test_Case_Response_Time")
log.info testRunner.testCase.testSuite.getTestCaseByName("Test_Case_00: Setup").getPropertyValue("Test_Case_Response_Time")
//-----------------------------------------------
}
//-----------------------------------------------
}
I have tried the following with no success:
log.info testRunner.testCase[kase.name].getPropertyValue("Test_Case_Response_Time")
log.info testRunner.testCase.testSuite.getTestCaseByName(kase.name).getPropertyValue("Test_Case_Response_Time")
The first line give me the following
groovy.lang.MissingPropertyException: No such property: Test_Case_00:
Setup for class: com.eviware.soapui.impl.wsdl.testcase.WsdlTestCase
error at line: 37
and the second line gives me the following error:
java.lang.NullPointerException: Cannot invoke method
getPropertyValue() on null object error at line:37
The below statement is not correct as testCase[kase.name] gives you property of testcase and not testcase itself
System is trying to search a property with the name"Test_Case_00: Setup" and hence giving error "No such property: Test_Case_00: Setup"
log.info testRunner.testCase[kase.name].getPropertyValue("Test_Case_Response_Time")
I was able to run the below code
log.info testRunner.testCase.testSuite.getTestCaseByName(kase.name).getPropertyValue("Test_Case_Response_Time")
In your actual code you have used the below line instead of kase.name
getTestCaseByName("**Test_Case_00: Setup**")
Looks like, testcase name is wrong, please copy the exact name and paste and it will work.
Below code worked for me. Its your code only.
def tSuite = testRunner.testCase.testSuite.project.getTestSuiteByName("TestSuite") // modified to run
tSuite.testCaseList.each
{ kase ->
//For each test CASE perform the following action
//-----------------------------------------------
kase.testStepList.each
{
//For each test step perform the following action
//-----------------------------------------------
}
//-----------------------------------------------
// log.info kase.name
// log.info testRunner.testCase[kase.name].getPropertyValue("Test_Case_Response_Time") <-- wrong syntax
log.info testRunner.testCase.testSuite.getTestCaseByName(kase.name).getPropertyValue("Test_Case_Response_Time")
}
I believe I was looking in the wrong Test Suite. Using the following i was able to get it to find the correct properties:
testRunner.testCase.testSuite.project.getTestSuiteByName(suite).getTestCaseByName(kase.name).getPropertyValue("Test_Case_Response_Time")
I'm using Hamcrest to unit test a REST API.
When I send a request, I often check for a 200 status code like this :
public void myTest() {
url = "route/to/my/rest/api/";
secured().when().get(url).then().statusCode(200);
}
But when I get a wrong code status, I only get an assertion error. Is there a way to automatically dump the response body (which contains the error) when the status code doesn't match ?
The secured() method :
public RequestSpecification secured() {
return given().header("Authorization", "Bearer " + getAuth());
}
As I mentioned in the comments I used the following
secured().when().post(url).then().log().ifValidationFails(LogDetail.BODY).statusCode(200);
You can find the source in the documentation
You can add a message to the assertion when test fails:
.statusCode(describedAs("The test fails because ...", is(200)))
I want to log exceptions while using VAVR (formerly javaslang). Below is the sample code snippet.
//will get 500 as response from this url
String sampleurl = "http://someurl.com";
List<String> myList = List.of(sampleurl);
LOGGER.info("In {} with urls {}",getClass(),myList);
return Observable.from(myList).flatMap(url ->
Observable.create(subscriber -> {
Try<String> httpEntity = HttpUtil.retrieveData(url).flatMap(httpResponse -> Try.of( () -> EntityUtils.toString(httpResponse.getEntity())));
httpEntity
.andThen(subscriber::onNext)
.andThen(subscriber::onCompleted)
.onFailure(subscriber::onError);
}));
I am trying to log exception in the onFailure() block but nothing gets logged. Please advise me on this.
Regards,
Jai
In both cases, success and failure, Vavr works as expected. Here are simple tests:
// prints nothing
Try.success("ok")
.andThen(() -> {})
.andThen(() -> {})
.onFailure(System.out::println);
// prints "java.lang.Error: ok"
Try.failure(new Error("ok"))
.andThen(() -> {})
.andThen(() -> {})
.onFailure(System.out::println);
I see two possible answers why the failure is not logged in your example:
the logger configuration does not fit your needs
the observables are not processed and Try is never called
Disclamer: I'm the creator of Vavr
I have a WebSocket in my Play application and I want to write a test for it, but I couldn't find any example on how to write such a test. I found a discussion in the play-framework Google group but there has been no activity recently.
So, are there any ideas on how to test WebSocket's in a Java test?
You can retrieve underlying Iteratee,Enumerator and test them directly. This way you don't need to use a browser. You need akka-testkit though, to cope with asynchronous nature of iteratees.
A Scala example:
object WebSocket extends Controller {
def websocket = WebSocket.async[JsValue] { request =>
Future.successful(Iteratee.ignore[JsValue] -> Enumerator.apply[JsValue](Json.obj("type" -> "error")))
}
}
class WebSocketSpec extends PlaySpecification {
"WebSocket" should {
"respond with error packet" in new WithApplication {
val request = FakeRequest()
var message: JsValue = null
val iteratee = Iteratee.foreach[JsValue](chunk => message = chunk)(Akka.system.dispatcher)
Controller.websocket().f(request)(Enumerator.empty[JsValue],iteratee)
TestKit.awaitCond(message == Json.obj("type" -> "error"), 1 second)
}
}
}
I test WebSockets code using Firefox:
https://github.com/schleichardt/stackoverflow-answers/commit/13d5876791ef409e092e4a097f54247d851e17dc#L8R14
For Java it works similar replacing 'HTMLUNIT' with 'FIREFOX': http://www.playframework.com/documentation/2.1.x/JavaFunctionalTest
Chrome provides a plugin to test websocket service.
Edit
So using the plugin (as shown in picture below) you can provide websocket url and the request data and send message to service. And message log shows the message sent from client and also service response.
Assume that you have a websocket library that returns the Future[Itearatee[JsValue, Unit], Enumerator[JsValue]] your controller uses
trait WSLib {
def connect: Future[Itearatee[JsValue, Unit], Enumerator[JsValue]]
}
And you wanna test this library.
Here is a context you can use:
trait WebSocketContext extends WithApplication {
val aSecond = FiniteDuration(1, TimeUnit.SECONDS)
case class Incoming(iteratee: Iteratee[JsValue, Unit]) {
def feed(message: JsValue) = {
iteratee.feed(Input.El(message))
}
def end(wait: Long = 100) = {
Thread.sleep(wait) //wait until all previous fed messages are handled
iteratee.feed(Input.EOF)
}
}
case class OutGoing(enum: Enumerator[JsValue]) {
val messages = enum(Iteratee.fold(List[JsValue]()) {
(l, jsValue) => jsValue :: l
}).flatMap(_.run)
def get: List[JsValue] = {
Await.result(messages, aSecond)
}
}
def wrapConnection(connection: => Future[Iteratee[JsValue, Unit], Enumerator[JsValue]]): (Incoming, OutGoing) = {
val (iteratee, enumerator) = Await.result(conn, aSecond)
(Incoming(iteratee), OutGoing(enumerator))
}
}
Then your tests can be written as
"return all subscribers when asked for info" in new WebSocketContext {
val (incoming, outgoing) = wrapConnection(myWSLib.connect)
incoming.feed(JsObject("message" => "hello"))
incoming.end() //this closes the connection
val responseMessages = outgoing.get //you only call this "get" after the connection is closed
responseMessages.size must equalTo(1)
responseMessages must contain(JsObject("reply" => "Hey"))
}
Incoming represent the messages coming from the client side, while the outgoing represents the messages sent from the server. To write test, you first feed in the incoming messages from incoming and then close the connection by calling incoming.end, then you get the complete list of outgoing messages from the outgoing.get method.
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.