объект readonly для модульного тестирования удаляется при использовании 'using' - PullRequest
0 голосов
/ 09 марта 2020

У меня есть объект, который используется несколько раз в одном и том же модульном тесте, и в других модульных тестах в пределах того же класса, который определяется следующим образом:

private readonly Task<HttpResponseMessage> successfulResponse = Task.FromResult(
            new HttpResponseMessage()
            {
                StatusCode = System.Net.HttpStatusCode.OK,
                Content = new StringContent(@"{""EntitySets"":[{""ResultSets"":[{""Results"":[{""Type"":""Message""}],""Total"":2}],""EntityType"":""Message""}]}")
            });

Затем в каждом из моих соответствующие юнит-тесты, я делаю что-то вроде этого:

mockHttpClient.Setup(m => m.SendAsync(It.Is<HttpRequestMessage>(v =>
            v.RequestUri.Host.Equals("example.com")),
            It.IsAny<CancellationToken>())).Returns(successfulResponse);

... где mockHttpClient - это издевательство HttpClient.

Но когда я юнит-тестирование, это Логика c выполняется во многих местах тестируемого кода:

using (HttpResponseMessage response = await this.client.SendAsync(request, cancellationToken))
{
//...
}

... где this.client - это mockHttpClient сверху. Как вы можете сказать, Moq предоставляет здесь мой заранее подготовленный объект successfulResponse для имитации ответа http.

Проблема в том, что самое первое выполнение такого using оператор выполняется, он удаляет successfulResponse, когда выходит из блока using, и все последующие блоки using терпят неудачу со следующим исключением:

Test method TestProbe_Success threw exception: 
    System.ObjectDisposedException: Cannot access a disposed object.
    Object name: 'System.Net.Http.StringContent'.

Так что мой вопрос, как я могу препятствует тому, чтобы тестируемый код избавлялся от этого объекта, который используется несколько раз в одном и том же модульном тесте и в других модульных тестах?

1 Ответ

0 голосов
/ 10 марта 2020

Проблема в том, что вы используете общий ресурс в своих тестах, который, если он будет уничтожен одним тестом, вызовет нежелательные эффекты в другом.

Измените его на функцию

private readonly Func<Task<HttpResponseMessage>> successfulResponse = () => Task.FromResult(
        new HttpResponseMessage() {
            StatusCode = System.Net.HttpStatusCode.OK,
            Content = new StringContent(@"{""EntitySets"":[{""ResultSets"":[{""Results"":[{""Type"":""Message""}],""Total"":2}],""EntityType"":""Message""}]}")
        });

и программа установки использует делегата в своих возвратах

mockHttpClient
    .Setup(m => m.SendAsync(It.Is<HttpRequestMessage>(v => 
            v.RequestUri.Host.Equals("example.com")
        ),
        It.IsAny<CancellationToken>())
    )
    .Returns(successfulResponse());

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

...