即使实际实现工作正常,RestSharp IRestClient 的模拟也会失败并出现 NullReferenceException

问题描述 投票:0回答:1

我已经为此绞尽脑汁好几天了,需要向社区询问这个问题。我已经用 C# 开发了一段时间,但对于实际使用异步还很陌生。我正在制作一个 Rest API 客户端并决定使用 RestSharp。我本来希望使用 Execute 或者 ExecuteTaskAsync,但自从我上次查看 RestSharp 以来,这两种方法似乎已被弃用,因此看起来我需要使 RestClient 上的 ExecuteAsync 工作。

过去几天我一直在搜索 stackoverflow 和其他参考资料,试图解决这个问题。大多数参考文献似乎都很旧,并且引用了几年前的 Execute 或 ExecuteTaskAsync,因此我从所有这些来源以及大量时间的测试和重写中拼凑而成。

我能够获得以下实现来针对真实的 API 工作(出于业务目的调整了一些变量),但是该类的实现工作正常。它返回预期的 RestResponse,我可以从中获取 RestResponse.Content。

但是,当我尝试为该方法设置单元测试时,我遇到了使用 IRestClient 的模拟版本时方法失败的问题。它一直说我有一个 NullReferenceExcption 但不清楚问题到底出在哪里。对于此示例,我使用 .netframework 4.8 和 RestSharp v110.2.0.0。

作为异步的新手,我尝试了各种不同的方法来配置模拟设置和返回,但我愿意审查和测试您可能有建议的任何其他配置。非常感谢任何帮助弄清楚我在哪里/为什么得到空引用的帮助。谢谢!

班级

using RestSharp;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace MyLib.Classes.Samples
{
    public interface IAuthSample
    {
        string GetResponse();
        Task<RestResponse> MakeAuthApiCallAsync();
    }

    public class AuthSample : IAuthSample
    {
        public string Url;
        public string Key;
        public string Secret;
        public IRestClient Client;

        public string GetResponse()
        {
            this.Url = "http://test.com;
            this.Key = "12345";
            this.Secret = "54321";

            var response = MakeAuthApiCallAsync().GetAwaiter().GetResult();
            return response.Content;
        }


        public virtual async Task<RestResponse> MakeAuthApiCallAsync()
        {
            var options = new RestClientOptions(this.Url)
            {
                MaxTimeout = -1,
            };

            // Set up api request
            var request = new RestRequest("oauth/token", Method.Post);
            request.AddHeader("Content-Type", "application/x-www-form-urlencoded");

            request.AddParameter("grant_type", "client_credentials");
            request.AddParameter("client_id", this.Key);
            request.AddParameter("client_secret", this.Secret);

            // Set up rest client if it doesn't exist
            IRestClient client = this.Client ?? new RestClient(options);

            // Contact api and get result
            var task = await client.ExecuteAsync<RestResponse>(request, CancellationToken.None);

            return task;
        }
    }
}

单元测试

using MyLib.Classes;
using Moq;
using RestSharp;
using System.Net;
using MyLib.Classes.Samples;

namespace MyLib.Test.Classes.Samples
{
    [TestFixture()]
    public class AuthSampleTests
    {
        [Test()]
        public void GetResponseTest()
        {
            Assert.Fail();
        }

        [Test()]
        public void TestMakeAuthApiCall_SupplyParameters_MatchResponseResults()
        {

            // Arrange

            var url = "http://test.com";
            var key = "12345";
            var secret = "54321";
            var auth = new AuthSample()
            {
                Url = url,
                Key = key,
                Secret = secret
            };
            

            var response = new RestResponse()
            {
                Content = "blah",
                StatusCode = HttpStatusCode.OK
            };

            var restClient = new Mock<IRestClient>() { CallBase = true };

            restClient.Setup(x => x.ExecuteAsync(It.IsAny<RestRequest>(), It.IsAny<CancellationToken>()))
                .ReturnsAsync(response);

            auth.Client = restClient.Object;

            // Act

            var result = auth.MakeAuthApiCallAsync().GetAwaiter().GetResult();

            // Assert

            Assert.Fail();

        }
    }
}

异常和堆栈

System.NullReferenceException
  HResult=0x80004003
  Message=Object reference not set to an instance of an object.
  Source=RestSharp
  StackTrace:
   at RestSharp.RestClientExtensions.<ExecuteAsync>d__10`1.MoveNext()
   at MyLib.Classes.Samples.AuthSample.<MakeAuthApiCallAsync>d__5.MoveNext() in C:\Users\bb\Documents\My Samples\VS Samples\MyApi\MyLib\Classes\Samples\AuthSample.cs:line 54

  This exception was originally thrown at this call stack:
    MyLib.Classes.Samples.AuthSample.MakeAuthApiCallAsync() in AuthSample.cs
c# .net asynchronous nunit restsharp
1个回答
0
投票

将代码更改为:

// Contact api and get result
var task = await client.ExecuteAsync(request, CancellationToken.None).ConfigureAwait(false);

您的代码的“问题”是您实际上正在调用扩展方法

RestClientExtensions.ExecuteAsync<T>
,如下所示:

 if (request == null) throw new ArgumentNullException(nameof(request));

var response = await client.ExecuteAsync(request, cancellationToken).ConfigureAwait(false);
return client.Serializers.Deserialize<T>(request, response, client.Options);

并且

client.Serializers
尚未设置,并且是
null

© www.soinside.com 2019 - 2024. All rights reserved.