Как реализовать статические «локальные тестовые» данные в тесте NUnit?

У меня есть пара тысяч тестов NUnit для библиотеки, многие из которых полагаются на наличие некоторого статически доступного «контекста запроса», который привязан к обслуживаемому запросу и проходит через задачи. Потребитель библиотеки предоставляет реализацию для извлечения текущего контекста запроса.

Мне нужно что-то реализовать, чтобы предоставить этот контекст для нашего тестового проекта NUnit, где контекст привязан к каждому отдельному запуску теста; каждый тестовый прогон должен иметь свой собственный объект, и я должен иметь доступ к нему из любого места во время теста.

Первоначально я добился этого, используя TestContext.Current.Properties и сохранив там свой контекст запроса, но с недавним обновлением NUnit Properties стал доступен только для чтения.

Есть ли замена, которую я могу использовать для получения «тестовых локальных» данных? то есть что-то, что ограничено текущим тестовым прогоном и доступно статически.


person Collin Dauphinee    schedule 06.04.2018    source источник


Ответы (1)


Похожая проблема на github содержит следующее заявление от разработчика NUnit:

Однако не предполагается, что вы должны изменять свойства теста NUnit, поскольку тест и его производные являются внутренними, и реализация может измениться. Внутренние классы допускают это, потому что это может потребоваться пользовательским атрибутам, но я рекомендую избегать этого в тестах.

И такое изменение реализации действительно произошло. До NUnit 2.6.0 у TestContext была сумка Properties, но с версии 2.6.0 она была перемещена в TestAdapter. Вы по-прежнему можете получить к нему доступ через TestContext.CurrentContext.Test.Properties, однако у вас нет гарантии, что это снова не изменится в будущем.

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

Вот рабочий образец:

internal static class ContextAccessor
{
    private static TestExecutionContext currentRequestTest;

    private static RequestContext currentRequestContext;

    public static RequestContext Current
    {
        get
        {
            var currTest = TestExecutionContext.CurrentContext;

            if (currentRequestTest == currTest)
            {
                return currentRequestContext;
            }

            currentRequestContext = CreateRequestContext();
            currentRequestTest = currTest;

            return currentRequestContext;
        }
    }

    public static RequestContext CreateRequestContext()
    {
        return new RequestContext();
    }
}

RequestContext вот ваш класс контекста. CreateRequestContext() — это, по сути, фабричный метод, создающий контекст. Вы можете поместить любую логику, необходимую для создания нового экземпляра контекста.

Теперь в тесте вы можете просто вызвать ContextAccessor.Current:

[Test]
public void SomeTest()
{
    var context1 = ContextAccessor.Current;
    var context2 = ContextAccessor.Current;

    Assert.AreSame(context1, context2);
}

Пример проекта на GitHub

person CodeFuller    schedule 06.04.2018