Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unit testing a REST client

I'm fairly new to unit testing but I'm trying to incorporate it into my development process for any new code I write (including bug fixes).

I'm working a REST client to communicate with Highrise (37Signals). How can I unit test this without relying on the external dependency? (The REST service).

For instance I'll have a method called GetPeople()

Things I'll want to unit test...

  1. The method returns the correct number of people in the account.
  2. The method returns null if there are no people in the account
  3. The method throws an exception if it can't connect to the service.

What do I do to test that the service still functions the same. I.E person still has a First Name? Can I unit test this or is this more of an integration test?

like image 502
BZink Avatar asked Sep 09 '11 14:09

BZink


3 Answers

I assume that your code now uses HttpWebRequest and HttpWebResponse directly. If that's the case, replace all occurrences of HttpWebRequest with IRequest and HttpWebResponse with IResponse. Defined these two interfaces and expose the properties and methods you need, like so:

public interface IRequest
{
    IResponse GetResponse(string url);
    IResponse GetResponse(string url, object data);
}

public interface IResponse
{
    Stream GetStream();
}

Then it's just to implement these interfaces twice; once for the real application (using HttpWebRequest and HttpWebResponse for doing the HTTP stuff) and once for the tests (not using HTTP, but instead perhaps writing to the console, a log or something similar).

Then, when instantiating your client, it's just to inject the implementation of IRequest you want:

var realClient = new Client(new MyHttpRequest());
var testClient = new Client(new MyTestRequest());
like image 166
Asbjørn Ulsberg Avatar answered Sep 29 '22 04:09

Asbjørn Ulsberg


For all those who are trying to test actual HttpWebRequest and HttpWebResponse, rather than the mocks. I have mentioned an approach here: http://nripendra-newa.blogspot.com/2012/10/testing-rest-clients.html. I'd call it an integration test rather than unit test though. Please refer here to see practical implementation: https://github.com/nripendra/Resty.Net/blob/master/tests/Resty.Net.Tests/RestRequestTest.cs

The approach:

  • Use embedded web server. I have used NancyFx, but you can use any e.g. kayak, cassini etc.
like image 26
Nripendra Avatar answered Sep 29 '22 04:09

Nripendra


It is a very common requirement to unit test code that interacts with external REST APIs. Simulating API servers is actually really annoying to set up usually because most web frameworks require lots of configuration before you can even begin to mock out endpoints. For example NancyFX and Asp.net.

In addition to this it can be really hard to assert the data that was sent to the server - essentially meaning you can only check that the response is handled correctly.

Even doing integration testing on the real endpoint you can't test what happens when the API you are using goes down or outputs an unusual status code, because you have no control over the endpoint.

After a long time trying to find a solution to this problem I decided to write a library for mocking out API endpoints using a real web server based on the built in HttpListener class.

https://github.com/paulmorrishill/FluentSimulator

This library supports simulating endpoints, headers, responses, slow responses, failed responses. Every type of event that can occur on an HTTP endpoint.

It also allows asserting that the data sent to the server was exactly what you expected it to be.

like image 42
user1486042 Avatar answered Sep 29 '22 02:09

user1486042