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;
In my scenario I wanted to use the built-deserialization and return a “MyResult".
This means that ExecuteAsync takes two parameters:
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.
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 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);
}
}