Unit testing Web Service responses - c#

I am currently writing an API wrapper in C# for ResellerClub's REST/HTTP API, which provides responses in garden-variety JSON objects. Invocation is performed by performing HTTP POST/GET on API endpoints using the HttpClient class. JSON.Net is used for parsing the responses.
How I can unit test my API wrapper functionality for the API as most calls require a level of expected state in order to succeed. For example, I cannot test the creation of a CNAME record on a domain that I have not already registered.
I understand that tests should never rely on state which they do not arrange themselves, and I've also been told that the tests should never actually deal with any kind of persistence mechanism such as a database. So, for the above example of a CNAME record, that as part of the "Arrange" phase of the test I should register a test domain, assert it worked, then do the actual CNAME function?
Alternative, should I come up with some way of mocking the JSON responses that are returned from the Reseller Club API?
EDIT: Example of my API class (ResellerClubApi.cs)
private async Task<string> DownloadString(string uri)
{
// HttpClient object downloads the JSON response string asynchronously
}
The DownloadString() method is used by my functionality as a generic means of grabbing the response from the third party service.
public async Task<List<string>> SuggestNames(string domainName)
{
// Calls DownloadString() with the correct URI, uses Newtonsoft.JSON to parse
// string representation of JSON into object
}
Methods such as SuggestNames() above are called like this from the higher service layer
public void someServiceLayerMethod()
{
var rcApi = new ResellerClubApi();
var x = rcApi.SuggestNames("something");
// ...
}
As you can see, I am a bit stuck as to how to mock JSON responses from the likes of HttpClient when my ResellerClubApi class is the lowest possible layer of my own code prior to doing things over HTTP.
I also don't know how to start using IoC to hand the HttpClient dependency...
Thanks

I would separate the code from your ResellerClubApi class which involves downloading stuff and authorization, and everything that involves connecting to a remote service, in let's say a ResellerClubClient and have it implement a IResellerClubClient interface.
public interface IResellerClubClient {
string RequestJson(string url);
}
public class ResellerClubClient : IResellerClubClient {
// implement your methods here
}
public ResellerClubApi : IResellerClubApi {
private readonly IResellerClubClient client;
// Pass the client as dependency, either manually or using Dependency framework of your choice
public ResellerClubApi(IResellerClubClient client) {
this.client = client;
}
public List<string> SuggestNames(string domainName) {
var jsonString = this.client.RequestJson("http://example.com/domains/?name="+domainName);
// decode it and do something with it
}
}
This allows you to test your ResellerClubApi class without being depending on a concrete IResellerClubClient implementation. And the best is, you can change it (from HttpClient to socket or whatever and don't ever have to touch your ResellerClubApi.
And then set up your Unit test in framework of your choice. Some example with Moq framework:
var mockedJsonString = '{ succes: true, names: ["domainA.com", "domainA.us"] }';
// create mockup object using IResellerClubClient interface
var resellerClubClient = new Mock<IResellerClubClient>();
// Tell the mock object to return "mockedJsonString" when any parameter is passed to RequestJsonString.
// If you do more than 1 call in a test, or if that's expected to be called multiple times inside
// the method to be tested, you can setup multiple conditions and results this way too
resellerClubClient.Setup(x => x.RequestJson(It.IsAny<string>())).Returns(mockedJsonString);
var api = new ResellerClubApi(resellerClubClient.Object);
List<string> names = api.SuggestNames("domain.com");
// do your assertions here
By having abstracted the connection and data retrieving methods into hit's own class represented by an interface, you made your Api class UnitTestable and easy to mock server responses.
Of course, the ResellerClubClient can't be Unit tested of course. But it can be done in an integration test or a verification test. A UnitTest should never involve connecting to a server or a database.

Here is a way to do it by mocking the HttpMessageHandler using Moq unit test. http://geekswithblogs.net/abhi/archive/2013/11/20/unit-tests-for-httpclient-using-httpmessagehandler.aspx

Related

How do I implement IHttpClientFactory with DI for unittesting purposes? [duplicate]

I am using the new Web API bits in a project, and I have found that I cannot use the normal HttpMessageRequest, as I need to add client certificates to the request. As a result, I am using the HttpClient (so I can use WebRequestHandler). This all works well, except that it isn't stub/mock friendly, at least for Rhino Mocks.
I would normally create a wrapper service around HttpClient that I would use instead, but I would like to avoid this if possible, as there are a lot of methods that I would need to wrap. I am hoping that I have missing something—any suggestions on how to stub HttpClient?
As an alternative to the excellent ideas already presented by #Raj, it may be possible to go a step lower and to mock/fake the HttpMessageHandler instead.
If you make any class that needs an HttpClient accept it as a dependency injection parameter in the constructor, then when unit testing you can pass in an HttpClient that has been injected with your own HttpMessageHandler. This simple class has only one abstract method that you need to implement, as follows:
public class FakeHttpMessageHandler : HttpMessageHandler
{
public HttpRequestMessage RequestMessage { get; private set; }
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
RequestMessage = request;
return Task.FromResult(new HttpResponseMessage(HttpStatusCode.OK));
}
}
My trivial example just saves the HttpRequestMessage in a public property for later inspection and returns HTTP 200 (OK), but you could augment this by adding a constructor that sets the result you want returned.
You'd use this class like this:
public void foo()
{
//Arrange
var fakeHandler = new FakeHttpMessageHandler();
var client = new HttpClient(fakeHandler);
var SUT = new ClassUnderTest(client);
//Act
SUT.DomSomething();
//Assert
fakeHandler.RequestMessage.Method.ShouldEqual(HttpMethod.Get); // etc...
}
There are limitations to this approach, for example in a method that makes multiple requests or needs to create multiple HttpClients, then the fake handler might start to become too complicated. However, it may be worth consideration for simple cases.
I released a library a few months ago called MockHttp which might be useful. It uses a custom HttpMessageHandler with a fluent (and extensible) API. You can inject the mocked handler (or HttpClient) into your service class and it will respond as it was configured.
Below shows basic usage. The When and Respond methods have a bunch of overloads, including running custom logic. The documentation on the GitHub page goes into a lot more detail.
var mockHttp = new MockHttpMessageHandler();
// Setup a respond for the user api (including a wildcard in the URL)
mockHttp.When("http://localhost/api/user/*")
.Respond("application/json", "{'name' : 'Test McGee'}"); // Respond with JSON
// Inject the handler or client into your application code
var client = new HttpClient(mockHttp);
var response = async client.GetAsync("http://localhost/api/user/1234");
// or without async: var response = client.GetAsync(...).Result;
var json = await response.Content.ReadAsStringAsync();
// No network connection required
Console.Write(json); // {'name' : 'Test McGee'}
I use Moq and I can stub out the HttpClient. I think this the same for Rhino Mock (I haven’t tried by myself).
If you just want to stub the HttpClient the below code should work:
var stubHttpClient = new Mock<HttpClient>();
ValuesController controller = new ValuesController(stubHttpClient.Object);
Please correct me if I’m wrong. I guess you are referring to here is that stubbing out members within HttpClient.
Most popular isolation/mock object frameworks won’t allow you to stub/setup on non- virtual members
For example the below code throws an exception
stubHttpClient.Setup(x => x.BaseAddress).Returns(new Uri("some_uri");
You also mentioned that you would like to avoid creating a wrapper because you would wrap lot of HttpClient members. Not clear why you need to wrap lots of methods but you can easily wrap only the methods you need.
For example :
public interface IHttpClientWrapper { Uri BaseAddress { get; } }
public class HttpClientWrapper : IHttpClientWrapper
{
readonly HttpClient client;
public HttpClientWrapper() {
client = new HttpClient();
}
public Uri BaseAddress {
get
{
return client.BaseAddress;
}
}
}
The other options that I think might benefit for you (plenty of examples out there so I won’t write the code)
Microsoft Moles Framework
http://research.microsoft.com/en-us/projects/moles/
Microsoft Fakes: (if you are using VS2012 Ultimate)
http://msdn.microsoft.com/en-us/library/hh549175.aspx

How to write Functional Tests against ServiceStack API

We have an ASP.NET Web Application wired up with ServiceStack. I've never written functional tests before, but have been tasked to write tests (nUnit) against our API and prove it's working all the way down to the Database level.
Can someone help me get started writing these tests?
Here's an example of a post method on our Users service.
public object Post( UserRequest request )
{
var response = new UserResponse { User = _userService.Save( request ) };
return new HttpResult( response )
{
StatusCode = HttpStatusCode.Created,
Headers = { { HttpHeaders.Location, base.Request.AbsoluteUri.CombineWith( response.User.Id.ToString () ) } }
};
}
Now I know how to write a standard Unit Test, but am confused on this part. Do I have to call the WebAPI via HTTP and initialize a Post? Do I just call the method like I would a unit test? I suppose it's the "Functional Test" part that eludes me.
Testing the service contract
For an end-to-end functional test, I focus on verifying that the service can accept a request message and produce the expected response message for simple use cases.
A web service is a contract: given a message of a certain form, the service will produce a response message of a given form. And secondarialy, the service will alter the state of its underlying system in a certain way. Note that to the end client, the message is not your DTO class, but a specific example of a request in a given text format (JSON, XML, etc.), sent with a specific verb to a specific URL, with a given set of headers.
There are multiple layers to a ServiceStack web service:
client -> message -> web server -> ServiceStack host -> service class -> business logic
Simple unit testing and integration testing is best for the business logic layer. It's usually easy write unit tests directly against your service classes too: it should be easy to construct a DTO object, call a Get/Post method on your service class, and validate the response object. But these do not test anything that's happening inside the ServiceStack host: routing, serialization/deserialization, execution of request filters, etc. Of course, you don't want to test the ServiceStack code itself as that's framework code that has its own unit tests. But there is an opportunity to test the specific path that a specific request message takes going into the service and coming out of it. This is the part of the service contract that can't be fully verified by looking directly at the service class.
Don't try for 100% coverage
I would not recommend trying to get 100% coverage of all business logic with these functional tests. I focus on covering the major use cases with these tests - one or two reqest examples per endpoint usually. Detailed testing of specific business logic cases is much more efficiently done by writing traditional unit tests against your business logic classes. (Your business logic and data access are not implemented in your ServiceStack service classes, right?)
The implementation
We are going to run a ServiceStack service in-process and use an HTTP client to send requests to it and then verify the content of the responses. This implementation is specific to NUnit; a similar implementation should be possible in other frameworks.
First, you need an NUnit setup fixture that runs one before all of your tests, to set up the in-process ServiceStack host:
// this needs to be in the root namespace of your functional tests
public class ServiceStackTestHostContext
{
[TestFixtureSetUp] // this method will run once before all other unit tests
public void OnTestFixtureSetUp()
{
AppHost = new ServiceTestAppHost();
AppHost.Init();
AppHost.Start(ServiceTestAppHost.BaseUrl);
// do any other setup. I have some code here to initialize a database context, etc.
}
[TestFixtureTearDown] // runs once after all other unit tests
public void OnTestFixtureTearDown()
{
AppHost.Dispose();
}
}
Your actual ServiceStack implementation probably has an AppHost class that's a subclass of AppHostBase (at least if it's running in IIS). We need to subclass a different base class to run this ServiceStack host in-process:
// the main detail is that this uses a different base class
public class ServiceTestAppHost : AppHostHttpListenerBase
{
public const string BaseUrl = "http://localhost:8082/";
public override void Configure(Container container)
{
// Add some request/response filters to set up the correct database
// connection for the integration test database (may not be necessary
// depending on your implementation)
RequestFilters.Add((httpRequest, httpResponse, requestDto) =>
{
var dbContext = MakeSomeDatabaseContext();
httpRequest.Items["DatabaseIntegrationTestContext"] = dbContext;
});
ResponseFilters.Add((httpRequest, httpResponse, responseDto) =>
{
var dbContext = httpRequest.Items["DatabaseIntegrationTestContext"] as DbContext;
if (dbContext != null) {
dbContext.Dispose();
httpRequest.Items.Remove("DatabaseIntegrationTestContext");
}
});
// now include any configuration you want to share between this
// and your regular AppHost, e.g. IoC setup, EndpointHostConfig,
// JsConfig setup, adding Plugins, etc.
SharedAppHost.Configure(container);
}
}
Now you should have an in-process ServiceStack service running for all of your tests. Sending requests to this service is pretty easy now:
[Test]
public void MyTest()
{
// first do any necessary database setup. Or you could have a
// test be a whole end-to-end use case where you do Post/Put
// requests to create a resource, Get requests to query the
// resource, and Delete request to delete it.
// I use RestSharp as a way to test the request/response
// a little more independently from the ServiceStack framework.
// Alternatively you could a ServiceStack client like JsonServiceClient.
var client = new RestClient(ServiceTestAppHost.BaseUrl);
client.Authenticator = new HttpBasicAuthenticator(NUnitTestLoginName, NUnitTestLoginPassword);
var request = new RestRequest...
var response = client.Execute<ResponseClass>(request);
// do assertions on the response object now
}
Note that you may have to run Visual Studio in admin mode in order to get the service to successfully open that port; see comments below and this follow-up question.
Going further: schema validation
I work on an API for an enterprise system, where clients pay a lot of money for custom solutions and expect a highly robust service. Thus we use schema validation to be absolutely sure we don't break the service contract at the lowest level. I don't think schema validation is necessary for most projects, but here's what you can do if you want to take your testing a step further.
One of the ways in which you can inadventently break your service's contract is to change a DTO in a way that is not backward compatible: e.g., rename an existing property or alter custom serialization code. This can break a client of your service by making data no longer available or parseable, but you typically can't detect this change by unit testing your business logic. The best way to prevent this from happening is to keep your request DTOs separate and single-purpose and separate from your business/data access layer, but there's still a chance someone will accidentally apply a refactoring incorrectly.
To guard against this, you can add schema validation to your functional test. We do this only for specific use cases that we know a paying client is actually going to use in production. The idea is that if this test breaks, then we know that the code that broke the test would break this client's integration if it were to be deployed to production.
[Test(Description = "Ticket # where you implemented the use case the client is paying for")]
public void MySchemaValidationTest()
{
// Send a raw request with a hard-coded URL and request body.
// Use a non-ServiceStack client for this.
var request = new RestRequest("/service/endpoint/url", Method.POST);
request.RequestFormat = DataFormat.Json;
request.AddBody(requestBodyObject);
var response = Client.Execute(request);
Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.OK));
RestSchemaValidator.ValidateResponse("ExpectedResponse.json", response.Content);
}
To validate the response, create a JSON Schema file that describes the expected format of the response: what fields are are required to exist for this specific use case, what data types are expected, etc. This implementation uses the Json.NET schema parser.
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Schema;
public static class RestSchemaValidator
{
static readonly string ResourceLocation = typeof(RestSchemaValidator).Namespace;
public static void ValidateResponse(string resourceFileName, string restResponseContent)
{
var resourceFullName = "{0}.{1}".FormatUsing(ResourceLocation, resourceFileName);
JsonSchema schema;
// the json file name that is given to this method is stored as a
// resource file inside the test project (BuildAction = Embedded Resource)
using(var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceFullName))
using(var reader = new StreamReader(stream))
using (Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceFileName))
{
var schematext = reader.ReadToEnd();
schema = JsonSchema.Parse(schematext);
}
var parsedResponse = JObject.Parse(restResponseContent);
Assert.DoesNotThrow(() => parsedResponse.Validate(schema));
}
}
Here's an example of a json schema file. Note that this is specific to this one use case and is not a generic description of the response DTO class. The properties are all marked as required as these are the specific ones the client are expecting in this use case. The schema might leave out other unused properties that currently exist in the response DTO. Based on this schema, the call to RestSchemaValidator.ValidateResponse will fail if any of the expected fields are missing in the response JSON, have unexpected data types, etc.
{
"description": "Description of the use case",
"type": "object",
"additionalProperties": false,
"properties":
{
"SomeIntegerField": {"type": "integer", "required": true},
"SomeArrayField": {
"type": "array",
"required": true,
"items": {
"type": "object",
"additionalProperties": false,
"properties": {
"Property1": {"type": "integer", "required": true},
"Property2": {"type": "string", "required": true}
}
}
}
}
}
This type of test should be written once and never modified unless the use case it's modeled on becomes obsolete. The idea is that these tests will represent actual usages of your API in production and ensure that the exact messages your API promises to return do not change in a way that breaks existing usages.
Other info
ServiceStack itself has some examples of running tests against an in-process host, on which the above implementation is based.

Add unit test case to test external webservice (.asmx) .NET

I have made a code to read the external web service and find the expose methods and their parameters using System.Web.Services.ServiceDescription.
I am also able to invoke the method and get the output through webservice.
This is done only on the bases of external Web service Url.
Everything is done from CodeBehind (C#).
I need to add the unit test case to test the functionality by adding dummy .asmx webservice which will be accessed by unit test.
Please let me know or have suggestion to how can i create a dummy service on the fly and used.
As far as I can see, there 2 different functionalists:
WSDL provider - i.e. class which gets a valid wsdl from somewhere
WSDL parser - the class which parses the wsdl and extracts the data
Here is a pseudo-code implementation of these to make them easy to mock and unit test.
public interface IWSDLProvider
{
string GetWsdlFromService(string url);
}
public class MyWsdlProvider : IWSDLProvider
{
private readonly IWebWrapper _webCLient;
public MyWsdlProvider(IwebWrapper webClient)
{
_webClient = webCLient;
}
public string GetWsdlFromService(string url)
{
//do here whatever is needed with the webClient to get the wsdl
}
}
public interface IWSDLParser
{
MyServiceData GetServiceDataFromUrl(string url);
}
public class MyWsdlParser : IWSDLParser
{
private readonly IWSDLProvider _wsdlProvider;
public MyWsdlParser(IWSDLProvider wsdlProvider)
{
_wsdlProvider = wsdlProvider;
}
public MyServiceData GetServiceDataFromUrl(string url)
{
//use the wsdl provder to fetch the wsdl
//and then parse it
}
}
The IWebClient is a wrapper around WebClient to allow easy mocking.
Using any mocking framework with the above code, you can easily isolate and mock any part, and test only the behavior at hand. That way, you can even make the mock for the wsdl provider to return any wsdl you want to test with.
You can go even further and wrap/isolate the System.Web.Services.ServiceDescription calls, so you don't really have to pass even a wsdl in your tests, just work on the results.

Run Nunit assertions from another class

I have two classes that I made to build up an order. Basically the class to create the order works fine but I want to use assertions to validate the information that comes back. The first class builds up the order with generic values and gets it ready for me to apply the actual information in the other class. Here is a sample:
public static OrderService Build(int Id, string password)
{
var req = new OrderRequest
{
Start = run,
Passsword = password,
ID = custId,
};
return req;
}
Here is a sample of the class that would test the results with sample data I pass through:
[TestCase(12565, "passWord")]
public static void Case(int custId, string password)
{
var create = new Order();
var req = Order.Build(custId, password);
if (req == null) return;
create.Resp = ws.Run(req) as OrderResponse;
Assert.IsNotNull(create.Resp);
}
These tests will run on their own and order the service whatever it is but my problem is being able to implement the assertions into the first class so I don't have to put that into the actual test case. I am using requests and responses from web services so it kind of gets sticky for me.
Thanks!
You should use a mocking framework such as moq rather than actually calling a web service.
Calls to external technologies such as databases or web services would not be included in unit-tests. Unit-tests test business logic.
Unit test: tests the internal workings of a class - typically at the method level. It should be a stand-alone test which is not related to other resources or systems.
Integration test: tests the correct inter-operation of multiple subsystems.

Stubbing or Mocking ASP.NET Web API HttpClient

I am using the new Web API bits in a project, and I have found that I cannot use the normal HttpMessageRequest, as I need to add client certificates to the request. As a result, I am using the HttpClient (so I can use WebRequestHandler). This all works well, except that it isn't stub/mock friendly, at least for Rhino Mocks.
I would normally create a wrapper service around HttpClient that I would use instead, but I would like to avoid this if possible, as there are a lot of methods that I would need to wrap. I am hoping that I have missing something—any suggestions on how to stub HttpClient?
As an alternative to the excellent ideas already presented by #Raj, it may be possible to go a step lower and to mock/fake the HttpMessageHandler instead.
If you make any class that needs an HttpClient accept it as a dependency injection parameter in the constructor, then when unit testing you can pass in an HttpClient that has been injected with your own HttpMessageHandler. This simple class has only one abstract method that you need to implement, as follows:
public class FakeHttpMessageHandler : HttpMessageHandler
{
public HttpRequestMessage RequestMessage { get; private set; }
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
RequestMessage = request;
return Task.FromResult(new HttpResponseMessage(HttpStatusCode.OK));
}
}
My trivial example just saves the HttpRequestMessage in a public property for later inspection and returns HTTP 200 (OK), but you could augment this by adding a constructor that sets the result you want returned.
You'd use this class like this:
public void foo()
{
//Arrange
var fakeHandler = new FakeHttpMessageHandler();
var client = new HttpClient(fakeHandler);
var SUT = new ClassUnderTest(client);
//Act
SUT.DomSomething();
//Assert
fakeHandler.RequestMessage.Method.ShouldEqual(HttpMethod.Get); // etc...
}
There are limitations to this approach, for example in a method that makes multiple requests or needs to create multiple HttpClients, then the fake handler might start to become too complicated. However, it may be worth consideration for simple cases.
I released a library a few months ago called MockHttp which might be useful. It uses a custom HttpMessageHandler with a fluent (and extensible) API. You can inject the mocked handler (or HttpClient) into your service class and it will respond as it was configured.
Below shows basic usage. The When and Respond methods have a bunch of overloads, including running custom logic. The documentation on the GitHub page goes into a lot more detail.
var mockHttp = new MockHttpMessageHandler();
// Setup a respond for the user api (including a wildcard in the URL)
mockHttp.When("http://localhost/api/user/*")
.Respond("application/json", "{'name' : 'Test McGee'}"); // Respond with JSON
// Inject the handler or client into your application code
var client = new HttpClient(mockHttp);
var response = async client.GetAsync("http://localhost/api/user/1234");
// or without async: var response = client.GetAsync(...).Result;
var json = await response.Content.ReadAsStringAsync();
// No network connection required
Console.Write(json); // {'name' : 'Test McGee'}
I use Moq and I can stub out the HttpClient. I think this the same for Rhino Mock (I haven’t tried by myself).
If you just want to stub the HttpClient the below code should work:
var stubHttpClient = new Mock<HttpClient>();
ValuesController controller = new ValuesController(stubHttpClient.Object);
Please correct me if I’m wrong. I guess you are referring to here is that stubbing out members within HttpClient.
Most popular isolation/mock object frameworks won’t allow you to stub/setup on non- virtual members
For example the below code throws an exception
stubHttpClient.Setup(x => x.BaseAddress).Returns(new Uri("some_uri");
You also mentioned that you would like to avoid creating a wrapper because you would wrap lot of HttpClient members. Not clear why you need to wrap lots of methods but you can easily wrap only the methods you need.
For example :
public interface IHttpClientWrapper { Uri BaseAddress { get; } }
public class HttpClientWrapper : IHttpClientWrapper
{
readonly HttpClient client;
public HttpClientWrapper() {
client = new HttpClient();
}
public Uri BaseAddress {
get
{
return client.BaseAddress;
}
}
}
The other options that I think might benefit for you (plenty of examples out there so I won’t write the code)
Microsoft Moles Framework
http://research.microsoft.com/en-us/projects/moles/
Microsoft Fakes: (if you are using VS2012 Ultimate)
http://msdn.microsoft.com/en-us/library/hh549175.aspx

Categories