Using the TestNG ITestContext to create smarter REST Assured tests
This post was published on March 9, 2016In this post, I would like to demonstrate two different concepts that I think work very well together:
- How to store and retrieve data objects using the TestNG ITestContext for better code maintainability
- How to communicate with RESTful web services that use basic or OAuth2 authorization using REST Assured
Using the PayPal sandbox API as an example, I will show you how you can create readable and maintainable tests for secured APIs using TestNG and REST Assured.
The TestNG ITestContext
If you have a suffficiently large test suite, chances are high that you want to be able to share objects between individual tests to make your tests shorter and easier to maintain. For example, if you are calling a web service multiple times throughout your test suite and that web service requires an authentication token in order to be able to consume it, you might want to request and store that authentication token in the setup phase of your test suite, then retrieve and use it in all subsequent tests where this web service is invoked. This is exactly the scenario we’ll see in this blog post.
TestNG offers a means of storing and retrieving objects between tests through the ITestContext interface. This interface allows you to store (using the inherited setAttribute() method) and retrieve (using getAttribute()) objects. Since the ITestContext is created once and remains active for the duration of your test run, this is the perfect way to implement object sharing in your test suite. Making the ITestContext available in your test methods is easy: just pass it as a parameter to your test method (we’ll see an example further down).
REST Assured authentication options
As you might have read in one of my previous blog posts, REST Assured is a Java library that allows you to write and execute readable tests for RESTful web services. Since we’re talking about secured APIs here, it’s good to know that REST Assured supports the following authentication mechanisms:
- Basic
- Digest
- OAuth (version 1 and 2)
- Form
In the examples in this post, we’ll take a closer look at both Basic authentication (for requesting an OAuth token) and OAuth2 authentication (for invoking secured web service operations) in REST Assured.
The PayPal sandbox API
To illustrate the concepts introduced above I chose to use the PayPal sandbox API. This is a sandbox version of the ‘live’ PayPal API that can be used to test applications that integrate with PayPal, as well as to goof around. It’s free to use for anybody that has an active PayPal account. You can find all documentation on the API here.
Retrieving an Oauth2 access token
The first step – after creating the necessary test accounts in the sandbox environment – is to construct a call in REST Assured that retrieves an OAuth2 authentication token from the PayPal web service. This request uses basic authentication and looks like this:
@BeforeSuite public void requestToken(ITestContext context) { String response = given(). parameters("grant_type","client_credentials"). auth(). preemptive(). basic("client_id","secret"). when(). post("https://api.sandbox.paypal.com/v1/oauth2/token"). asString(); }
The actual values for client_id and secret are specific to the PayPal sandbox account. Note that we have stored the JSON response as a string. This makes it easier to parse it, as we will see in a moment. The response to this request contains our OAuth2 authentication token:
In order to store this token for use in our actual tests, we need to extract it from the response and store it in the TestNG ITestContext:
JsonPath jsonPath = new JsonPath(response); String accessToken = jsonPath.getString("access_token"); context.setAttribute("accessToken", accessToken); System.out.println("Access token: " + context.getAttribute("accessToken"));
The System.out.println output shows us we have successfully stored the OAuth2 access token in the ITestContext:
Using the OAuth2 access token in your tests
Next, we want to use the previously stored token in subsequent API calls that require OAuth2 authentication. This is fairly straightforward: see for example this test that verifies that no payments have been made for the current test account:
@Test public void checkNumberOfAssociatedPaymentsIsEqualToZero(ITestContext context) { given(). contentType("application/json"). auth(). oauth2(context.getAttribute("accessToken").toString()). when(). get("https://api.sandbox.paypal.com/v1/payments/payment/"). then(). assertThat(). body("count", equalTo(0)); }
Note the use of context.getAttribute() to retrieve the token from the ITestContext. This test passes, which not only tells us that no payments have yet been made by this account, but also that our authentication worked as expected (otherwise, we would have received an authentication error).
Download an example project
The Maven project containing all code from this post can be downloaded here.