Reputation: 9352
I'm trying to unit test this method which uses RestSharp (version 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;
}
This is what I tried:
[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"));
}
This code builds, but throws a runtime exception that prevents my test from working:
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.
It appears there is no way for me to test my method if it includes a call to .AddDefaultHeader
. I considered creating my own mock object, but the IRestClient interface requires dozens of methods.
Any suggestions on how to test my method?
Upvotes: 3
Views: 3387
Reputation: 6252
If you want to check whether a default header was added you could use a spy
like so:
[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);
}
This uses the .Callback
functionality of Moq
which adds the added Parameter
to the spy
.
This works because you can see in the source code for RestSharp
that this extension method
calls AddDefaultParameter
which in turn adds a Parameter
to the DefaultParameters
:
restClient.DefaultParameters.Add(p);
This example uses xUnit
as a test runner, but the rest should be the same.
Upvotes: 3
Reputation: 246998
Moq does not mock extension methods. Figure out what the extension method accesses and that is what you mock.
The source for that extension method is available and ultimately calls
/// <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;
}
So depending on what you need to access, then restClient.DefaultParameters
is what needs to be mocked.
If no actual functionality is actually needed and this is just to avoid null reference exception then set up the mock to stub all available properties using SetupAllProperties
//...
mockRestClient.SetupAllProperties();
//...
Upvotes: 2