如何模拟 RestSharp AddDefaultHeader 方法
How to mock RestSharp AddDefaultHeader method
我正在尝试对使用 RestSharp(版本 106.6.9)的方法进行单元测试:
public UserInfo GetUserInfo(string oauthToken)
{
_restClient.AddDefaultHeader("Authorization", "Bearer " + oauthToken);
var request = new RestRequest(_userInfoUrl);
var response = _restClient.Execute<UserInfo>(request);
if (!response.IsSuccessful)
{
throw new ApplicationException("Request for user info failed with HTTP status code " + response.StatusCode);
}
return response.Data;
}
这是我试过的:
[Test]
public void ShouldFailIfOAuthTokenExpired()
{
var mockRestClient = new Mock<IRestClient>();
mockRestClient.Setup(m => m.AddDefaultHeader("Authorization", "Bearer Some expired token"));
mockRestClient.Setup(m => m.Execute(It.IsAny<IRestRequest>())).Returns(new RestResponse() { StatusCode = System.Net.HttpStatusCode.Unauthorized });
var svc = new MyService(mockRestClient.Object, "my endpoint");
Assert.Throws<ApplicationException>(() => svc.GetUserInfo("Some expired token"));
}
此代码已构建,但抛出运行时异常阻止我的测试工作:
System.NotSupportedException : Unsupported expression: m => m.AddDefaultHeader("Authorization", "Bearer Some expired token")
Extension methods (here: RestClientExtensions.AddDefaultHeader) may not be used in setup / verification expressions.
如果我的方法包含对 .AddDefaultHeader
的调用,我似乎无法测试我的方法。我考虑创建自己的模拟对象,但 IRestClient 接口需要许多方法。
关于如何测试我的方法有什么建议吗?
如果您想检查是否添加了默认 header,您可以使用 spy
,如下所示:
[Fact]
public void Test()
{
var mock = new Mock<IRestClient>();
var spy = new List<Parameter>();
mock
.Setup(m => m.DefaultParameters.Add(It.IsAny<Parameter>()))
.Callback((Parameter p) => spy.Add(p));
var instance = mock.Object;
instance.AddDefaultParameter(new Parameter("Foo", "Bar", ParameterType.Cookie));
Assert.Equal("Bar", spy.Single().Value);
}
这使用 Moq
的 .Callback
功能,将添加的 Parameter
添加到 spy
。
这是有效的,因为您可以在 RestSharp
的 source code 中看到此 extension method
调用 AddDefaultParameter
,后者又将 Parameter
添加到 DefaultParameters
:
restClient.DefaultParameters.Add(p);
本例使用xUnit
作为测试运行器,其他应该是一样的
Moq 不模拟扩展方法。找出扩展方法访问的内容,这就是您模拟的内容。
该扩展方法的源代码可用并最终调用
/// <summary>
/// Add a parameter to use on every request made with this client instance
/// </summary>
/// <param name="restClient">The IRestClient instance</param>
/// <param name="p">Parameter to add</param>
/// <returns></returns>
public static IRestClient AddDefaultParameter(this IRestClient restClient, Parameter p)
{
if (p.Type == ParameterType.RequestBody)
{
throw new NotSupportedException(
"Cannot set request body from default headers. Use Request.AddBody() instead.");
}
restClient.DefaultParameters.Add(p);
return restClient;
}
因此,根据您需要访问的内容,restClient.DefaultParameters
就是需要模拟的内容。
如果实际上不需要任何实际功能,这只是为了避免空引用异常,则使用 SetupAllProperties
设置模拟以存根所有可用属性
//...
mockRestClient.SetupAllProperties();
//...
我正在尝试对使用 RestSharp(版本 106.6.9)的方法进行单元测试:
public UserInfo GetUserInfo(string oauthToken)
{
_restClient.AddDefaultHeader("Authorization", "Bearer " + oauthToken);
var request = new RestRequest(_userInfoUrl);
var response = _restClient.Execute<UserInfo>(request);
if (!response.IsSuccessful)
{
throw new ApplicationException("Request for user info failed with HTTP status code " + response.StatusCode);
}
return response.Data;
}
这是我试过的:
[Test]
public void ShouldFailIfOAuthTokenExpired()
{
var mockRestClient = new Mock<IRestClient>();
mockRestClient.Setup(m => m.AddDefaultHeader("Authorization", "Bearer Some expired token"));
mockRestClient.Setup(m => m.Execute(It.IsAny<IRestRequest>())).Returns(new RestResponse() { StatusCode = System.Net.HttpStatusCode.Unauthorized });
var svc = new MyService(mockRestClient.Object, "my endpoint");
Assert.Throws<ApplicationException>(() => svc.GetUserInfo("Some expired token"));
}
此代码已构建,但抛出运行时异常阻止我的测试工作:
System.NotSupportedException : Unsupported expression: m => m.AddDefaultHeader("Authorization", "Bearer Some expired token")
Extension methods (here: RestClientExtensions.AddDefaultHeader) may not be used in setup / verification expressions.
如果我的方法包含对 .AddDefaultHeader
的调用,我似乎无法测试我的方法。我考虑创建自己的模拟对象,但 IRestClient 接口需要许多方法。
关于如何测试我的方法有什么建议吗?
如果您想检查是否添加了默认 header,您可以使用 spy
,如下所示:
[Fact]
public void Test()
{
var mock = new Mock<IRestClient>();
var spy = new List<Parameter>();
mock
.Setup(m => m.DefaultParameters.Add(It.IsAny<Parameter>()))
.Callback((Parameter p) => spy.Add(p));
var instance = mock.Object;
instance.AddDefaultParameter(new Parameter("Foo", "Bar", ParameterType.Cookie));
Assert.Equal("Bar", spy.Single().Value);
}
这使用 Moq
的 .Callback
功能,将添加的 Parameter
添加到 spy
。
这是有效的,因为您可以在 RestSharp
的 source code 中看到此 extension method
调用 AddDefaultParameter
,后者又将 Parameter
添加到 DefaultParameters
:
restClient.DefaultParameters.Add(p);
本例使用xUnit
作为测试运行器,其他应该是一样的
Moq 不模拟扩展方法。找出扩展方法访问的内容,这就是您模拟的内容。
该扩展方法的源代码可用并最终调用
/// <summary>
/// Add a parameter to use on every request made with this client instance
/// </summary>
/// <param name="restClient">The IRestClient instance</param>
/// <param name="p">Parameter to add</param>
/// <returns></returns>
public static IRestClient AddDefaultParameter(this IRestClient restClient, Parameter p)
{
if (p.Type == ParameterType.RequestBody)
{
throw new NotSupportedException(
"Cannot set request body from default headers. Use Request.AddBody() instead.");
}
restClient.DefaultParameters.Add(p);
return restClient;
}
因此,根据您需要访问的内容,restClient.DefaultParameters
就是需要模拟的内容。
如果实际上不需要任何实际功能,这只是为了避免空引用异常,则使用 SetupAllProperties
//...
mockRestClient.SetupAllProperties();
//...