几天来,我一直在为这件事绞尽脑汁,我需要向社会提出这个问题.我用C#开发已经有一段时间了,但对实际使用异步非常陌生.我正在制作一个rest API客户端,并决定使用RestSharp.我希望使用Execute或ExecuteTaskAsync,但似乎自从我上次查看RestSharp以来,这两个方法已被弃用,因此看起来我需要使RestClient上的ExecuteAsync工作.
在过go 的几天里,我一直在搜索StackOverflow和其他参考文献,试图梳理这一点.大多数参考资料似乎都很陈旧,它们都提到了几年前的Execute或ExecuteTaskAsync,所以我从所有这些来源中拼凑了出来,并花费了大量时间进行测试和重写.
我能够让下面的实现针对真实的API工作(出于业务目的调整了一些变量),但是类的实现工作得很好.它返回预期的RestResponse,我可以从中获取RestResponse.Content.
但是,当我try 为该方法设置单元测试时,在使用模拟版本的IRestClient时遇到了方法失败的问题.它一直说我有一个NullReferenceExcption,但不清楚问题的确切位置.对于这个样例,我使用的是.netFramework4.8和RestSharpv110.2.0.0.
作为异步的新手,我已经try 了各种不同的方法来配置模拟设置和返回,但我愿意判断和测试您可能对此有建议的任何其他配置.任何帮助我弄清楚我在哪里/为什么得到空引用的帮助都是非常感谢的.谢谢!
Class
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;
}
}
}
Unit Test
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();
}
}
}
Exception and Stack
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