We have learned a lot in the previous sections, but the only method we used so far was HTTP get. It’s time to move on and learn to use other other methods, in particular, post and delete. They’re not the only ones. There are methods such as patch and or put, but if you learn how to do post, then you should be able to send put as well, perhaps with a little help of public documentation.
Overview:
- OPTIONS – Allowed API Methods. We’ll use it to confirm that the Web API under test indeed supports these operations.
- HTTP DELETE. Why not POST first? Because creating a valid post request with all the bells and whistles is more complex.
- HTTP POST – get an understanding of what is important, and then build on that knowledge and learn how to post.
Sending an OPTIONS Request
We have been sending only get requests and get arguably is supported by all Web APIs, because its fundamental purpose is to serve information, but when it comes to posting and deleting, that’s a different story. Some APIs might not support that.
The good news is that we can ask the Web API what it supports and what it doesn’t. To do that, we need to send an options request. What the API will do is send the response containing the answer to that question, along with the status code 204: No Content. It’s very similar to 200. The only difference is that 204 is more specific.
- 200 OK means the request went fine, but you don’t know if you should get or should not get any content in the body.
- 204 also tells you that your request has been processed without problems, but it also tells you explicitly not to expect anything in the body. All information is in the headers.
So let’s write a test that verifies that the API gives us the correct answer. Obviously, this depends on each individual API, but in our case, it is going to be GET, POST, PATCH, PUT and DELETE.
@Test
public void optionsReturnsCorrectMethodsList() throws IOException{
String header = "Access-Control-Allow-Methods";
String expectedReply = "GET, POST, PATCH, PUT, DELETE";
HttpOptions request = new HttpOptions(BASE_ENDPOINT);
response = client.execute(request);
String actualValue = ResponseUtils.getHeader(response, header);
Assert.assertEquals(actualValue, expectedReply);
}
We created an options object just like the get object. We passed in the BASE_ENDPOINT. We executed that request, we got the response back. Then we reused our little util method to extract the header. The header that we want is: Access-Control-Allow-Methods. We finished our test with the assert and….passed!
Now we can be sure that posting and deleting is supported. Needless to say, as a tester, you should use business requirements of your project to learn about such things, what methods are supported and such.
Sending a DELETE Request
We need to create a delete, send a delete, get the response, and get the status code. Everything is pretty standard. Let’s create the delete object using the new keyword.
Just like the get and options, we specify the full URL. Let’s delete a repository. I have created a repository on my GitHub account. I called it hello-world and that’s the endpoint to which we’ll send the delete request:
https://api.github.com/repos/olealea/hello-world
We then use a client to execute that request and save the response. Then we get the status code, like we did several times with get. And finally assert. The expected status code this time is 204: No Content. Run the test.
Failed. Expected 204, but found 403 – Forbidden.
So the server understood what you want to do, but refuses to execute your command, and that makes sense, since I haven’t provided any credentials. Deleting is a permanent, destructive change so it’s only natural that we need to provide credentials such as login and password.
So how do we provide the credentials? The first thing to remember is that HTTP response is not the only one that has headers and a body. Our request also has headers and a body; it’s just until now, we never set anything explicitly in those. So all we have to do is to add a header to our request, specifically, the header called Authorization.
Let’s get back to our test, and see what options are available on the request object. As we can see, there is an option to set a header. Let’s use the one taking two parameters. First we supply the name, and the Apache developers were again nice enough to supply us with a class that collects a lot of standard headers we might want to use, including AUTHORIZATION; and that’s the one we need. And the second value is the actual value, but what should we provide here? Login, password, smth else..?
Let’s take a step back and see what kind of Authentication Mechanisms there are. There are quite a few. We’ll just mention the three most popular:
- Basic authentication
- OAuth and OAuth2
- JWT – JSON Web Tokens
There’s a course on Pluralsight that touches these technologies: Introduction to OAuth2, OpenID Connect and JSON Web Tokens (JWT) by Dominick Baier
In this section, we’ll be using a token and basic methods, since these two are supported by GitHub API, one for deleting, and the other for posting. For the delete operation, let’s use the token method. You need first to have your own account on Github.com.
Go to github.com/setting/tokens -> Personal access tokens -> Generate new token -> grant maximum privileges and click the green button Generate -> copy the token.
For security reasons I have erased my credentials, but there should be paste your token. Now we are ready to send the request again, with an extra-header that contains the security token that should tell the API that I have enough credentials to execute a delete statement. Run that test and…Passed! 😉
Now it’s high time to learn how to create something using the post method.
Sending a POST Request
Posting is arguably the most complex operation that you need to carry out. It’s a multi-step process. First, you have to supply the extra authentication header, but you also need to create and set the content that you want to post. So if you want to create a new repository, you need to construct a valid JSON and insert it into the body of the request.
Let’s write down the steps we need to do, so we won’t get lost:
- Create an HttpPost with a valid Endpoint. That’s where all the repositories live.
- Set the Basic Auth Header with valid login and password. As the second parameter, we could just supply the token again and be done with it, but if the API supports Basic authentication, it should be tested as well. Arguably, it could be an entirely separate test, but we’re going to do both in this one test: verify that basic authentication works and that posting a repository works as well.
- Define Json object to Post and set it as the Entity of the request – in other words, populate the body of the request. For that, we use the method setEntity which accepts only entity objects, so we create a new one inside. Let’s use the constructor with two parameters. Second – content type, and first – a string variable. Let’s create it too, and specify the name of the new repository.
- Send it. Worst is over! Just execute this request, get the status from the response, and verify it’s a 201; 201 – stands for Created. Run the test and…GREEN! :*
Let’s implement that, and then explain (my login:password of github are hidden in orange):
Encoding is not encryption
Basic authentication means supplying with login and password separated by a colon. This login plus password needs to be encoded into Base64.
byte[] encodedAuth = Base64.encodeBase64(auth.getBytes(Charset.forName("ISO-8859-1")));
This line of code returns an array of bytes, which then needs to be converted back into a string and appended to Basic like so:
String authHeader = "Basic " + new String(encodedAuth);
So in the end, you will be sending a header with a value similar to this:
Yes, that looks like a randomly hashed string containing random characters. You might think, if this can be encoded, then it can be very easily decoded, and that is correct.
Bear in mind that encoding is not encryption, meaning it’s not meant to hide your credentials.
The purpose of the Base64 encoding is to convert any characters that are not HTTP compatible to characters that are compatible with HTTP. When it comes to security, Basic authentication must be sent only over HTTPS, never plain HTTP.
A Quick Note on the Basic Authentication..
There is a lot of debate on the internet how safe or unsafe it is. Basic authentication over plain HTTP is definitely very unsafe, but over HTTPS, some argue is reasonable in some cases. Others argue that it should be avoided as much as possible anyway.
Now, if you are not a security expert but a quality assurance professional, it’s not your job to argue what’s best in terms of security, unless you know what you’re talking about. However, if a decision has been made to use Basic authentication, then it is definitely your job to test that it works properly, and that’s what we did here.
Run all dat tests at once!
Before we finish, let us take all of our tests and run them. We’ve put in a lot of effort writing all of these tests, overcoming multiple issues, so let’s see what we achieved.
Hurray! All 18 tests passed.
Summary
- OPTIONS. First we used the OPTIONS method to check what methods the Web API supports and confirmed that it does accept Post and Delete.
- DELETE & POST. We then went on and learned how to use POST and DELETE. As we found out, these methods weren’t as easy as the Get method. Because they make permanent changes, they can’t be executed without proper authentication.
- Authorization. We took a look at what ways we can tell the API, hey, I have the credentials to delete something or create something for a particular account. In our case, we used a web token for DELETE and Basic authentication for POST, although in real life, you would better have an entirely separate test verifying the functionality of authentication, and then choose one of them as the default way to authenticate and execute all of your post and delete tests.
This concludes our course, Getting Started with Web API Test Automation in Java, presented by Andrejs on Pluralsight.com. We now have the necessary foundation knowledge to assess what tools we need to automate API tests, and if you decide to go with your own automation framework, the required skills to start doing automation in Java using the Apache HTTP Client Library. It is definitely not the one out there, so you’re not limited to the one we’ve been using. If you’re curious, you can shop around and see what other libraries are available and what the code looks like.
Has been a pleasure to take this course and make the notes of every step. Thank you for being here with me, ma dear. Bye! 😉