我已经为此绞尽脑汁好几天了,需要向社区询问这个问题。我已经用 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
将代码更改为:
// 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
。