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...
- The method returns the correct number of people in the account.
- The method returns null if there are no people in the account
- 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开发者_StackOverflow.E person still has a First Name? Can I unit test this or is this more of an integration test?
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());
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.
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.
This is a textbook example for using a mock object. So what you have to do is to implement a fake server simulating the behaviour you are expecting.
精彩评论