【问题标题】:How to mock RestSharp portable library in Unit Test如何在单元测试中模拟 RestSharp 便携式库
【发布时间】:2017-03-07 11:14:05
【问题描述】:

我想为测试目的模拟 RestClient 类

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;
    }

}

我的测试课:

[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);
    }
}

但我无法实例化RestResponse 对象,出现以下错误:

.Returns(new RestResponse<T>
{
    Data = JsonConvert.DeserializeObject<T>(json),
    StatusCode = httpStatusCode
});

无法在此处访问受保护的内部构造函数“RestResponse”。

我该如何解决这个问题?我在 Xamarin 便携式库上使用 FubarCoder.RestSharp nuget 包。

【问题讨论】:

  • 模拟 IRestResponse&lt;T&gt; 并返回

标签: c# unit-testing xamarin moq restsharp


【解决方案1】:

模拟 IRestResponse&lt;T&gt; 并将其返回

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;
}

测试也应该更新为异步

[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);
}

【讨论】:

  • @Nkosi 我尝试使用您的方法,但出现以下错误:“T”必须是具有公共无参数构造函数的非抽象类型才能将其用作泛型中的参数“T”类型或方法“RestClient.Execute(RestRequest)”。你知道我为什么会得到这个吗?
  • @alminh 正如错误消息所解释的,您可能使用的是抽象类型。
  • 感谢您的回复。我需要在 MockRestClient 方法上添加约束 where T : new() 。现在可以正常使用了。
  • @alminh 你是对的。我查看了 Github 上的源代码,并意识到缺少约束。我已经更新了答案以反映这一变化。
【解决方案2】:

我没有找到任何好的答案,所以我最终编写了一个帮助库。我将它发布到 NuGet - MoqRestSharp.Helpers。该项目旨在帮助对 RestSharp 进行单元测试,因为它扩展了 Mock,因此这有助于我测试我的 RestSharp 请求和响应错误处理。

它使用最小起订量

随时欢迎反馈!

【讨论】:

    【解决方案3】:

    完整的解决方案

    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; }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-06-14
      • 2015-01-19
      • 1970-01-01
      • 2013-10-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-11-24
      相关资源
      最近更新 更多