1

I am learning Karate DSL in order to determine if it is a viable automation solution for our new API.

We have a unique environment in which we have a REST API to test, but also use REST services to perform other required actions while the original request is awaiting a response. The REST calls perform robotic actions to manipulate hardware, query our servers, etc.

We need the ability to send a REST request, perform various other REST requests (with assertions) while awaiting a response to the first request. Then, finally assert that the original request gets the correct response payload based on the actions performed between the first request and its response.

Rough example:

Feature: Async test

  Background:
    * def defaultAssertion = { success: true }
    Given url 'http://foo/'

  Scenario: Foo test
    Given path 'start' <- start long running call
    When method get
    And request { externalId: 'id1'}

    Given path 'robot-action' <- perform another call that resolves immediately
    When method get
    Then status 200
    * match response contains deep defaultAssertion

    Then status 200 <- somehow assert on first requests' response
    * match response contains deep defaultAssertion

Obviously the example above does not work, but I am hoping we can structure our tests similarly.

I know tests can run in parallel, but I am not sure how to encapsulate them as "one test" vs "multiple tests" and control order (which is required for this to work properly).

There is documentation on Async behavior, but I found it difficult to follow. If anyone can provide more context on how to implement the example I would greatly appreciate it.

Any suggestions would be warmly welcomed and examples would be fantastic. Thanks all!

  • well, I tried my best to make that async example a simple one. can you see if this q & a resolves your questions and I will close this question as a duplicate: https://stackoverflow.com/q/74375701/143475 – Peter Thomas Dec 07 '22 at 17:03
  • Thank you for the quick reply! I did see that post and that graphic, but I think I am getting wrapped around the axle trying to understand if the example is using a mock server and if the wait blocks other actions until a response is received because this won't work for our use case. I may be completely misunderstanding the example though, so please excuse my naivety. – brotatochip04 Dec 07 '22 at 17:27
  • okay, I gave it some thought and came up with an answer. – Peter Thomas Dec 07 '22 at 17:36

2 Answers2

0

Actually being able to wait for an HTTP call to complete and do other things in the meantime is something Karate cannot do by default. This question has me stumped and it has never been asked for before.

The only way I think we can achieve it in Karate is to create a thread and then run a feature from there. There is a Java API to call a feature, but when you are doing all that, maybe you are better off using some hand-crafted Java code to make an HTTP request. Then your case aligns well with the example mentioned here: https://twitter.com/getkarate/status/1417023536082812935

So to summarize, my opinion of the best plan of action.

  1. for this "special" REST call, be prepared to write Java code to make that HTTP call on a separate thread
  2. call that Java code at the start of your Karate test (using Java interop)
    • you can pass the karate JS object instance
    • so that you can call karate.listen() when the long-running job is done
    • actually instead of the above, just use a CompletableFuture and a java method call (just like the example linked above)
  3. Now that step won't block and you can do anything you want
  4. After you have done all the other work, use the listen keyword or call a Java method on the helper you used at the start of your test (just like the linked example)

That should be it ! If you make a good case for it, we can build some of this into Karate, and I will think over it as well.

Peter Thomas
  • 54,465
  • 21
  • 84
  • 248
  • 1
    Ok, this makes much more sense to me now. Thank you for the thoughtful response! Having built-in support for this behavior would be amazing, but I am not sure if others have similar use cases. If we can get Karate working for our purposes we will be using heavily going forward. Thanks again! – brotatochip04 Dec 07 '22 at 17:49
-1

Feature: Async test

Background: * def defaultAssertion = { success: true } Given url 'http://foo/'

Scenario: Foo test Given path 'start' <- start long running call When method get And request { externalId: 'id1'}

Given path 'robot-action' <- perform another call that resolves immediately
When method get
Then status 200
* match response contains deep defaultAssertion

Then status 200 <- somehow assert on first requests' response
* match response contains deep defaultAssertion