How to Mock RestSharp.ExecuteAsync

It took me a while to figure out how to Mock RestSharp’s ExecuteAsync method for unit testing purposes. Once you realise that ExecuteAsync takes a callback which is called when the REST call completes it all becomes reasonably straightforward, using Mocks Callback function;
Mock<IRestClient> restClient = new Mock<IRestClient>();
restClient.Setup(c => c.ExecuteAsync<MyResult>(
Moq.It.IsAny<IRestRequest>(),
Moq.It.IsAny<Action<IRestResponse<MyResult>, RestRequestAsyncHandle>>()))
.Callback<IRestRequest, Action<IRestResponse<MyResult>, RestRequestAsyncHandle>>((request, callback) =>
{
var responseMock = new Mock<IRestResponse<MyResult>>();
responseMock.Setup(r => r.Data).Returns(new MyResult() { Foo = "Bar" });
callback(responseMock.Object, null);
});

In my scenario I wanted to use the built-deserialization and return a “MyResult".
This means that ExecuteAsync takes two parameters:
  • An IRestRequest
  • A callback, which is an Action<IRestResponse<AuthorisationResponse>, RestRequestAsyncHandle>

    That is just the callback you pass in and it is a delegate that takes two parameters, namely the IRestResponse and a RestRequestAsyncHandle.
When you are running this for real, RestSharp will execute your IRestRequest and then call your callback with the result. So in our Unit test, we can use Mock’s Callback feature to call your callback straight away. To your code that will just look like the website responded really quickly.

When I actually call the callback function, I also use Mock to mock the IRestResponse and just configure that mock to return a concrete instance of MyResult.

EDIT 9 November 2013

A fuller example:

public class Sud
{
private IRestClient client;

public Sud(IRestClient client)
{
this.client = client;
}

public MyResult Foo()
{
// NOTE: This code is obviously stupid; it just blocks the thread until the async task completes, which is rather pointless.
// It's just an example :)
MyResult result = null;
var request = new RestRequest();
var blocker = new AutoResetEvent(false);

this.client.ExecuteAsync<MyResult>(
request,
response =>
{
result = response.Data;
blocker.Set();
});
blocker.WaitOne();
return result;
}
}

public class MyResult
{
public string Name { get; set; }
}

[TestFixture]
public class Tests
{
[Test]
public void TestFoo()
{
Mock<IRestClient> restClient = new Mock<IRestClient>();
restClient.Setup(c => c.ExecuteAsync<MyResult>(
Moq.It.IsAny<IRestRequest>(),
Moq.It.IsAny<Action<IRestResponse<MyResult>, RestRequestAsyncHandle>>()))
.Callback<IRestRequest, Action<IRestResponse<MyResult>, RestRequestAsyncHandle>>((request, callback) =>
{
var responseMock = new Mock<IRestResponse<MyResult>>();
responseMock.Setup(r => r.Data).Returns(new MyResult() { Name = "Billy Bob" });
callback(responseMock.Object, null);
});

var Subject = new Sud(restClient.Object);

var result = Subject.Foo();

Assert.IsNotNull(result);
Assert.AreEqual("Billy Bob", result.Name);
}
}