7

We use a proprietary framework based on the REST-assured library and TestNG to automate API testing for our REST web services. I saw some api testing code which uses Thread.sleep(n seconds) to wait for a response to be returned. This seems wrong to me because the response times can vary. I believe that there should be a better way to wait for a response, i.e. wait only as much as necessary. Maybe I could poll every few milliseconds, or by use an observer (test)-observed (api) design pattern, or something else. I am not sure.

How do I wait for an api to return a response ?

This is what the code looks like:

@Test
public void doApiTesting() throws Exception 
{   
    framework.loginUser(User);
    framework.createNewData();//Takes some time.
    Thread.sleep(10000);
}

2 Answers 2

8

HTTP is a synchronous protocol* so active polling is not an option. You need to wait until client receives response or request times out. There are two ways to constrain synchronous behaviour with timeout.

One is to set a timeout for receiving a response. REST-Assured uses Apache HTTP Client for which you can set http.socket.timeout and http.connection.timeout. See answers for Apache HttpClient timeout and Apache HTTP Client documentation.

Another solution is to set a certain timeout for a block of your test code:

new TimeLimitedCodeBlock(5, TimeUnit.MINUTES) { 

  @Override 
  public void codeBlock() {
     framework.createNewData();//Takes some time.
  }

}.run();

TimeLimitedCodeBlock is described in answers to Java: set timeout on a certain block of code?.

*Synchronous communication

In program-to-program communication, synchronous communication requires that each end of an exchange of communication respond in turn without initiating a new communication. A typical activity that might use a synchronous protocol would be a transmission of files from one point to another. As each transmission is received, a response is returned indicating success or the need to resend. Each successive transmission of data requires a response to the previous transmission before a new one can be initiated.

EDIT

Active polling is not an option, because waiting for HTTP Response is synchronous: it blocks the current thread until response is received. TimeLimitedCodeBlock class I mentioned waits for HTTP Response in a separate thread. The separate thread terminates when HTTP Response is received or time out passes. Instead of actively checking (polling) if a separate thread has received HTTP response, TimeLimitedCodeBlock is waiting for a separate thread to terminate.

2
  • Could you please explain why polling is not an option in synchronous protocols such as HTTP ? Thank you.
    – JohnSink
    Commented Sep 7, 2017 at 0:00
  • @JohnSink Hopefully, I explained. Does it make sense now?
    – dzieciou
    Commented Sep 7, 2017 at 12:40
1

I wrote a custom wait method for the same purpose. You can create a similar one to match your needs. The method below waits atMost TIMEOUT seconds or until the API response has the expectedString

public String waitUntilStringFoundInResponse(String apiPath, HashMap<String, String> parameters, String findMe, int TIMEOUT) throws Exception {
    String result = null;
    int i = 0;
    while (i < TIMEOUT) {
        result = postHttpsRequest(apiPath, parameters);
        if (result.contains(findMe)) {
            break;
        } else {
            TimeUnit.SECONDS.sleep(1);
            ++i;
            if (i == TIMEOUT) {
                throw new TimeoutException("Timed out after waiting for " + i + " seconds");
            }
        }
    }
    return result;
}

There is also a method in org.awaitility.Awaitility that can be used for the same purpose, but the method runs on a different thread, so I was having session issues. Here is the documentation for that if you prefer to use that instead of writing a custom one.

5
  • I guess postHttpsRequest is a synchronous call to REST API. The problem with this solution is that it will repeat POST Request multiple times (maximually TIMEOUT times). Awaitlity works in a similar way. It performs active polling . That's why Awaitlity is called "DSL" for synchronizing asynchronous operations, while HTTP is basically synchronous protocol.
    – dzieciou
    Commented Sep 6, 2017 at 19:33
  • right. That is what I wanted. i.e. I wanted to wait until the API response contained particular string. eg. I am doing a search on something and there is a delay in getting the results. So the API response might not have the expected string until after waiting for a few seconds. So I keep executing the POST request until the response has the String. Does that make sense?
    – Anu
    Commented Sep 6, 2017 at 19:35
  • Yes, it makes sense, but this is not what the OP asked for :-)
    – dzieciou
    Commented Sep 6, 2017 at 19:38
  • 1
    Oops sorry about that. I just read the question again and realized that myself. I will delete my answer :)
    – Anu
    Commented Sep 6, 2017 at 19:39
  • Anu, perhaps you don't need to delete it because the discussion below your answer clarifies the problem better.
    – dzieciou
    Commented Sep 6, 2017 at 19:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.