Sunday, 27 March 2016

How to Write Integration Test for Web API

I’ll give just an idea of what integration tests are and how can we write it. Integration tests doesn’t run in memory. For WebAPI’s the best practice to write integration test is when the WebAPI is self hosted.You can try writing integration test when you host an API, so that you you get an actual URL or endpoint of the service you want to test.The test is performed on actual data and actual service. Let’s proceed with an example. I have hosted my web api and I want to test GetAllProducts() method of WebAPI.My hosted URL for the particular controller action is http://localhost:50875/v1/Products/Product/allproducts.
Now I know that I am not going to test my controller method through dll reference but I want to actually test its endpoint for which I need to pass an authentication token because that end point is secured and can not be authorized until I add a secure token to the Request header. Following is the integration test forGetAllProducts().
[Test]
public void GetAllProductsIntegrationTest()
{
    #region To be written inside Setup method specifically for integration tests
        var client = new HttpClient { BaseAddress = new Uri(ServiceBaseURL) };
        client.DefaultRequestHeaders.Add("Authorization", "Basic YWtoaWw6YWtoaWw=");
        MediaTypeFormatter jsonFormatter = new JsonMediaTypeFormatter();
        _response = client.PostAsync("login", null).Result;

        if (_response != null && _response.Headers != null && _response.Headers.Contains("Token") && _response.Headers.GetValues("Token") != null)
        {
        client.DefaultRequestHeaders.Clear();
        _token = ((string[])(_response.Headers.GetValues("Token")))[0];
        client.DefaultRequestHeaders.Add("Token", _token);
        }
    #endregion

    _response = client.GetAsync("v1/Products/Product/allproducts/").Result;
    var responseResult =
    JsonConvert.DeserializeObject<List<ProductEntity>>(_response.Content.ReadAsStringAsync().Result);
    Assert.AreEqual(_response.StatusCode, HttpStatusCode.OK);
    Assert.AreEqual(responseResult.Any(), true);
}
I have used same class to write this test, but you should always keep your unit tests segregated from integration tests, so use another test project to write integration tests for web api. First we have to request a token and add it to client request,
var client = new HttpClient { BaseAddress = new Uri(ServiceBaseURL) };
client.DefaultRequestHeaders.Add("Authorization", "Basic YWtoaWw6YWtoaWw=");
MediaTypeFormatter jsonFormatter = new JsonMediaTypeFormatter();
_response = client.PostAsync("login", null).Result;

if (_response != null && _response.Headers != null && _response.Headers.Contains("Token") && _response.Headers.GetValues("Token") != null)
{
client.DefaultRequestHeaders.Clear();
_token = ((string[])(_response.Headers.GetValues("Token")))[0];
client.DefaultRequestHeaders.Add("Token", _token);
}
In above code I have initialized the client with running service’s base URL i.e. http://localhost:50875. After initialization I am setting a default request header to call my login endpoint of Authentication controller to fetch valid token.Once the user logs in with his credentials he get a valid token. To read in detail about security refer my article on security in web api. I have passed base 64 string of my credentials username :Akhil and password:Akhil for basic authentication. Once request gets authenticated, I get a valid token in _response.Headers that I fetch and assign to _token variable and add to client’s default header with this line of code,
_token = ((string[])(_response.Headers.GetValues("Token")))[0];
client.DefaultRequestHeaders.Add("Token", _token);
Then I am calling the actual service URL from the same client,
_response = client.GetAsync("v1/Products/Product/allproducts/").Result;

No comments:

Post a Comment