NSubstitute возвращает первое значение InlineData для всех тестов

Я относительно новичок в тестировании. Мы используем XUnit и NSubstitute в качестве наших сред тестирования, и у меня возникли проблемы с тем, что должно быть простым тестом. Я использую библиотеку классов для взаимодействия с внешним API, и мне нужно определить, доступен ли API перед выполнением операций. (Я должен упомянуть, что dll уже работает. Мы добавляем тесты задним числом.)

Проблема, с которой я сталкиваюсь, заключается в том, что независимо от того, что представляет собой InlineData для теста, замена (client.Execute...) всегда возвращает значение для первого значения InlineData. Если первое значение — HttpStatusCode.OK, то другие значения InlineData не проходят тест, поскольку замена возвращает только HttpStatusCode.OK. Если я поменяю местами OK с Forbidden, то HttpStatusCode.OK завершится ошибкой, потому что замена всегда возвращает Forbidden только как StatusCode.

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

Тест

[Theory]
[InlineData(HttpStatusCode.OK)]
[InlineData(HttpStatusCode.Forbidden)]
[InlineData(HttpStatusCode.BadRequest)]
[InlineData(HttpStatusCode.NotFound)]
public void ConnectionCheck(HttpStatusCode code)
{
    var d2lClient = new d2lClient("userid", "userkey", "mappid", "mappkey", "serviceurl.com", "1");
    var client = Substitute.For<IRestClient>();
    var authenticator = Substitute.For<iITGValenceAuthenticator>();

    client.Execute<WhoAmIUser>(Arg.Any<IRestRequest>()).ReturnsForAnyArgs(x => new RestResponse<WhoAmIUser>()
        {
            StatusCode = code
        });


    d2lClient.GetOrCreateRestClient(client);
    d2lClient.GetOrCreateAuthenticator(authenticator);

    if (code == HttpStatusCode.OK)
    {
        Assert.True(d2lClient.ConnectionCheck(), "client.ConnectionCheck() should be true for " + code);
    }
    else
    {
        Assert.False(d2lClient.ConnectionCheck(), "client.ConnectionCheck() should be false for " + code);
    }
}

Метод

public bool ConnectionCheck()
{
    if (_userId == null || _userKey == null || _mAppId == null || _mAppKey == null)
        return false;

    try
    {
        var response = GetRestResponse<WhoAmIUser>(_userId, _userKey, d2lRoute.WhoAmI());

        return response.StatusCode == HttpStatusCode.OK;
    }
    catch (Exception ex)
    {
        return false;
    }
}

public IRestResponse<T> GetRestResponse<T>(string userId, string userKey, string url, List<Parameter> parameters = null, IRestRequest request = null, IRestClient client = null, iITGValenceAuthenticator authenticator = null) where T : new()
{
    /*
       Irrelevant code
    */
    return _client.Execute<T>(request);
}

person TheErikPowell    schedule 28.04.2016    source источник


Ответы (1)


Спасибо Давиду Чепаку за помощь! Я взял его пример и немного изменил его, чтобы он соответствовал структуре кода. Когда я это сделал, и это сработало, стало ясно, что что-то не так с моей библиотекой классов. Оказывается, _client был случайно помечен как статический. Это не имело значения, пока мы не захотели протестировать его, и мне пришлось вытащить создание клиента, чтобы разрешить внедрение зависимостей. Раньше клиент был локальной переменной для каждого вызова API.

Как только модификатор static был удален из свойства _client, тесты заработали, как и ожидалось.

Измененный

private static IRestClient _client;
private static IRestRequest _request;

to

private IRestClient _client;
private IRestRequest _request;

в классе d2lClient.

person TheErikPowell    schedule 29.04.2016