I would like to mockup the RestClient class for test purposes
public class DataServices : IDataServices
{
private readonly IRestClient _restClient;
public DataServices(IRestClient restClient)
{
_restClient = restClient;
}
public async Task<User> GetUserByUserName(string userName)
{
User user = null;
// create a new request
var restRequest = new RestRequest("User", Method.GET);
// create REST parameters
restRequest.AddParameter("userName", userName, ParameterType.QueryString);
// execute the REST request
var restResponse = await _restClient.Execute<User>(restRequest);
if (restResponse.StatusCode.Equals(HttpStatusCode.OK))
{
user = restResponse.Data;
}
return user;
}
}
My test class :
[TestClass]
public class DataServicesTest
{
public static IRestClient MockRestClient<T>(HttpStatusCode httpStatusCode, string json)
{
var mockIRestClient = new Mock<IRestClient>();
mockIRestClient.Setup(x => x.Execute<T>(It.IsAny<IRestRequest>()))
.Returns(new RestResponse<T>
{
Data = JsonConvert.DeserializeObject<T>(json),
StatusCode = httpStatusCode
});
return mockIRestClient.Object;
}
[TestMethod]
public async void GetUserByUserName()
{
var dataServices = new DataServices(MockRestClient<User>(HttpStatusCode.OK, "my json code"));
var user = await dataServices.GetUserByUserName("User1");
Assert.AreEqual("User1", user.Username);
}
}
But I can't instantiate the RestResponse object, I've the following error:
.Returns(new RestResponse<T>
{
Data = JsonConvert.DeserializeObject<T>(json),
StatusCode = httpStatusCode
});
Cannot access protected internal constructor 'RestResponse' here.
How can I workaround this ? I'm using the FubarCoder.RestSharp nuget package on a Xamarin portable Library.
Mock IRestResponse<T> and return that
public static IRestClient MockRestClient<T>(HttpStatusCode httpStatusCode, string json)
where T : new() {
var data = JsonConvert.DeserializeObject<T>(json)
var response = new Mock<IRestResponse<T>>();
response.Setup(_ => _.StatusCode).Returns(httpStatusCode);
response.Setup(_ => _.Data).Returns(data);
var mockIRestClient = new Mock<IRestClient>();
mockIRestClient
.Setup(x => x.Execute<T>(It.IsAny<IRestRequest>()))
.ReturnsAsync(response.Object);
return mockIRestClient.Object;
}
The test should also be updated to be async as well
[TestMethod]
public async Task GetUserByUserName() {
//Arrange
var client = MockRestClient<User>(HttpStatusCode.OK, "my json code");
var dataServices = new DataServices(client);
//Act
var user = await dataServices.GetUserByUserName("User1");
//Assert
Assert.AreEqual("User1", user.Username);
}
I didn't find any great answers so I ended up writing a helper library. I published it to NuGet - MoqRestSharp.Helpers. This project is aimed to help unit test RestSharp as it extends Mock so this helped me test my RestSharp requests and response error handling.
It uses Moq
Feedback is always welcome!
Complete solution
using Moq;
using Newtonsoft.Json;
using NUnit.Framework;
using RestSharp;
using System.Net;
namespace RestMockTest
{
public class Tests
{
[Test]
public void Test1()
{
var client = MockRestClient<User>(HttpStatusCode.OK, "{\"Name\":\"User1\"}");
var restRequest = new RestRequest("api/item/", Method.POST);
var restResponse = client.Execute<User>(restRequest);
var user = restResponse.Data;
Assert.AreEqual("User1", user.Name);
}
public static IRestClient MockRestClient<T>(HttpStatusCode httpStatusCode, string json)
where T : new()
{
var data = JsonConvert.DeserializeObject<T>(json);
var response = new Mock<IRestResponse<T>>();
response.Setup(_ => _.StatusCode).Returns(httpStatusCode);
response.Setup(_ => _.Data).Returns(data);
var mockIRestClient = new Mock<IRestClient>();
mockIRestClient
.Setup(x => x.Execute<T>(It.IsAny<IRestRequest>()))
.Returns(response.Object);
return mockIRestClient.Object;
}
}
public class User
{
public string Name { get; set; }
}
}