Skip to content

James.Testing.Rest

Todd Meinershagen edited this page Jul 29, 2016 · 37 revisions

James.Testing.Rest

James.Testing.Rest is a dead simple library for calling rest-based services. It is designed to be simple enough for QA folks to leverage it in their own automation.

In order to add it to your projects, you can use the following in the NuGet package manager console.

>install-package James.Testing.Rest

Below is a description of the supported features. There will be more coming in the near future!

Requests

All requests begin with the Request keyword and use a fluent syntax going forward. No need for a novice coder to have to new() up any variables. Below is the simplest request involving a GET against a resource. All you need is a URI.

Example: Simplest request

Request
	.WithUri("http://www.somehost.com")
	.Get(); //returns an IResponse<dynamic, dynamic>

For any given request, you can add both headers and query string parameters, if you like.

Example: All of the available parts of a request

Request
	.WithUri("http://www.somehost.com")
	.WithHeaders(new { x_requested_with = "XMLHttpRequest", FirstName = "Todd" })
	.WithQuery(new { Id = 1, Test = "Some test value." })
	.Get(); //returns an IResponse<dynamic, dynamic>

Notice that the WithHeaders() method accepts an anonymous object with any number of properties. For each property, a header will be sent. If there are "_" in the name of the property, they will be replaced with "-" characters. In this case, the x_requested_with property renders a header as "x-requested-with".

Notice also that WithQuery() method accepts an anonymous object with any number of properties. For each property, a query string parameter will be sent with its corresponding value. All values are sent as strings, so the ToString() property of any value will be assigned.

All responses have a StatusCode, Body, and Headers.

Request
	.WithUri("http://www.somehost.com")
	.Get();
	.DebugPrint(r => r.StatusCode)
	.DebugPrint(r => r.Body)
	.DebugPrint(r => r.Headers);

Verifying a GET Request

Most of the time, testers will be calling your API and wanting to get back some information to verify. The Get() method provides an interface for specifying the uri and return type so that the tester can Verify() things in a strongly-typed setting.

Example: Getting a dynamic return object

Request
	.WithUri("http://www.somehost.com/Person/1")
	.Get()
	.Verify(r => r.Body.FirstName == "Todd");

Example: Gathering a list of entities

Request
	.WithUri("http://www.somehost.com/People")
	.Get<IEnumerable<Person>>()
	.Verify(r => r.Body.Count == 2)
	.VerifyThat(r => r.StatusCode).Is(HttpStatusCode.OK);

Example: Getting one entity

Request
	.WithUri("http://www.somehost.com/People/1")
	.Get<Person>()
	.Verify(r => r.Body.Id = 1)
	.Verify(r => r.Body.FirstName == "Todd")
	.Verify(r => r.Body.LastName = "Meinershagen");

Example: Getting a byte stream

Request
	.WithUri("http://www.somehost.com/Documents/1")
	.Get<byte[]>()
	.Verify(r => r.Body.Length == 212);

Verifying a POST Request

There will be times that testers want to create a resource and verify. The Post() method provides the ability to specify a uri, an object to post, and the return type so that the tester can Verify() things in a strongly-typed setting.

Example:

Request
	.WithUri("http://www.somehost.com/People")
	.Post<Person, Guid>(new Person{ Id = 2, FirstName = "Todd", LastName = "Meinershagen" })
	.VerifyThat(r => r.StatusCode).Is(HttpStatusCode.Created)
	.Verify(r => r.Body != Guid.Empty)
	.Verify(r => r.Headers.Location.OriginalString != string.Empty);

Verifying a DELETE Request

There will be times testers want to delete a resource and verify. The Delete() method provides the ability to specify a uri (including an id) and returns a response that has an empty body and a status code (200-OK, 202-Accepted, or 204-NoContent).

Example:

Request
	.WithUri("http://www.somehost.com/1")
	.Delete();
	.Verify(r => r.StatusCode == HttpStatusCode.NoContent);
	.Verify(r => string.IsNullOrEmpty(r.Body));

Verifying a PUT Request

Troubleshooting

Storing Out Parameters

Sometimes the fluent interface will not work for all test scenarios because you will need to make multiple calls and share data. In order to do this, the library provides a Store() method to allow you to output data from your responses in local variables.

Example:

string locationUri;

Request
	.WithUri("http://www.somehost.com/People")
	.Post<Person, Guid>(new Person{ Id = 2, FirstName = "Todd", LastName = "Meinershagen" })
	.Store(out locationUri, r => r.Headers.Location.OriginalString);

Request
	.WithUri(locationUri)
	.Get<Person>()
	.Verify(r => r.Body.Id = 2)
	.Verify(r => r.Body.FirstName == "Todd")
	.Verify(r => r.Body.LastName = "Meinershagen");

Debugging

The James.Testing.Rest library also provides methods for debugging your tests. In some cases, testers will want to write out to the console values within their tests as they are constructing them. This is achieved by simply calling the DebugPrint() method.

Example: Printing out a property

Request
	.WithUri("http://www.somehost.com/People/1")
	.Get<Person>()
	.DebugPrint(r => r.Body.FirstName);

Example: Printing out a message

Request
	.WithUri("http://www.somehost.com/People/1")
	.Get<Person>()
	.DebugPrint("I am now going to verify the last name.")
	.Verify(r => r.LastName == "Meinershagen");