Как смоделировать метод RestSharp AddDefaultHeader - PullRequest
1 голос
/ 14 октября 2019

Я пытаюсь провести модульное тестирование этого метода, который использует 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 требуются десятки методов.

Есть предложения о том, как протестировать мой метод?

Ответы [ 2 ]

1 голос
/ 14 октября 2019

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();

//...
1 голос
/ 14 октября 2019

Если вы хотите проверить, был ли добавлен заголовок по умолчанию, вы можете использовать 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);
    }

При этом используется .Callback функциональность Moq, которая добавляет добавленные Parameter * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *. * * * * * * *. * * * * * * * * * * * * * * * *. DefaultParameters:

restClient.DefaultParameters.Add(p);

В этом примере в качестве бегуна для тестирования используется xUnit, но все остальное должно быть таким же.

...