Mock RestClient.ExecuteAsync

RestSharp is not a stranger to developers, so is the usage. What this posts aims to explore is how to do Unit Test a method, involving a RestClient.ExecuteAsync call. To be more precise, the post explores how to mock the RestClient for the method.

Let’s consider the following code, taken from VSPostman, one of the side projects I am working on.

public async Task Get(string url)
{
if (string.IsNullOrWhiteSpace(url) || _parameterDictionary.Values.Contains(null)) throw new ArgumentNullException();

_restClient.BaseUrl = new Uri(url); // _restClient is an instance of RestClient
_restRequest.Method = Method.GET;
var _returnValue = new ResponseObject();
if(_parameterDictionary?.Count==0)
_restRequest.Parameters.AddRange(_parameterDictionary?.Select(x => new Parameter() {Name = x.Key, Value = x.Value }));
var tcs = new TaskCompletionSource();
var watch = Stopwatch.StartNew();
_restClient.ExecuteAsync(_restRequest, response =>
{
_returnValue.ContendType = response.ContentType;
_returnValue.ResponseString = response.Content;
_returnValue.StatusCode = response.StatusCode;
_returnValue.StatusDescription = response.StatusDescription;
_returnValue.ResponseTime = watch.Elapsed;
_returnValue.Length = response.ContentLength;
if (response.Headers != null)
_returnValue.Headers = response.Headers.ToDictionary(x => x.Name, y => y.Value as string);

tcs.SetResult(_returnValue);
});
return await tcs.Task;
}

As observed, the code raises a GET Request using the ReshSharp library. If I was using TDD and writing a Unit Test case for this method, how would I approach it ? How would I mock the RestSharp library calls ?

Of course, it is easy to understand that we need to create the mock object of IRestClient. But how do we create a response ? For this we attach a call back.

var expected = "response content";
var expectedBytes = Encoding.UTF8.GetBytes(expected);
Mock restClient = new Mock();
restClient.Setup(x => x.ExecuteAsync(
It.IsAny(),
It.IsAny<Action<IRestResponse, RestRequestAsyncHandle>>()))
.Callback<IRestRequest, Action<IRestResponse, RestRequestAsyncHandle>>((request, callback) =>
{
callback(new RestResponse { Content= expected }, null);
});
// act
var clientService = new ClientServiceUsingRestSharp(restClient.Object);
var actualResponse = await clientService.Get($"http://www.google.com");

That would be all you need. The callback would ensure you get the response from the mock object.

Mocking IDispossible with “Using”

Mocking objects is integral part of Unit Testing. The nucleus of Mocking is Dependency Injection, which allows us to inject Mock object into the code. But what happens when programmer has used the “Using” keyword ? For Example,

using(CustomDbCommand cmd = new CustomDbCommand ())
{
// Code
}
<pre>

This makes it difficult to mock DbCommand. The solution lies in deploying Factory Pattern to create our CustomDbCommand. For the purpose, I have created a IDbCommandFactory interface and its concrete solution in DbCommandFactory. It comprises of a method called CreateDbCommandObject, which returns a new instance of CustomDbCommand;

public interface IDbCommandFactory
{
CustomDbCommand CreateDbCommandObject();
}

public class DbCommandFactory : IDbCommandFactory
{
public CustomDbCommand CreateDbCommandObject()
{
return new CustomDbCommand();
}
}

Now that we have our Factory Object ready, it is time to inject it into our Repository Class. I prefer to use Constructor Injection for the purpose.


private readonly IDbCommandFactory objDbCommmandFactory;
public TestRepository( IDbCommandFactory DbCommandFactory)
{
objDbCommmandFactory = DbCommandFactory;
}

public void TestMethod()
{
using ( var cmd = objDbCommmandFactory.CreateDbCommandObject())
{
// Code
}
}

Now we are all set to Mock our CustomDbCommand Object, or in other words, our IDispossible object. Happy Unit Testing.