TransactionScope не выполняет откат в TearDown для каждого теста для интеграционного тестирования с использованием NUnitC#

Место общения программистов C#
Anonymous
TransactionScope не выполняет откат в TearDown для каждого теста для интеграционного тестирования с использованием NUnit

Сообщение Anonymous »

Сценарий

У меня есть API на ASP.NET Core 2.0, который интегрируется с базой данных MS SQL с помощью EF Core. Теперь я пытаюсь настроить для него тесты интеграции/API, используя NUnit и TestServer. Проблема в том, что мне нужно настроить каждый тест как «изолированный», поэтому по сути он должен очищать (откатывать) БД после себя. Я не могу использовать компенсационные транзакции для достижения желаемого результата из-за сложности БД (много устаревших вещей, которые нужно учитывать, например, триггеры и т. д.).

Настройка SUT API

Вот пример API, который я пытаюсь протестировать:

Код: Выделить всё

// GET api/values
[HttpGet]
public async Task Get(string dataName1, string dataName2)
{
using (var scope = CreateScope())
{
await _service.DoWork(dataName1);
await _service.DoWork(dataName2);
scope.Complete();
}
return Ok();
}
Метод DoWork() по сути ищет объект по переданному параметру и увеличивает его другое свойство. Затем просто вызывает SaveChanges().
CreateScope() — это вспомогательный метод, возвращающий экземпляр TransactionScope:

Код: Выделить всё

return new TransactionScope(
TransactionScopeOption.Required,
new TransactionOptions() { IsolationLevel = IsolationLevel.RepeatableRead },
TransactionScopeAsyncFlowOption.Enabled
);
Настройка интеграционного теста

Код: Выделить всё

[TestFixture]
[SingleThreaded]
[NonParallelizable]
public class TestTest
{
private TransactionScope _scope;

[Test]
public async Task Test11()
{
_scope = CreateScope();
var result = await Client.GetAsync("api/values?dataName1=Name1&dataName2=Name2");
Assert.DoesNotThrow(() => result.EnsureSuccessStatusCode());

_scope.Dispose();
_scope = null;
}
}
Здесь Клиент — это экземпляр HttpClient, созданный с использованием методов Microsoft.AspNetCore.TestHost.TestServer и CreateScope(). на самом деле такой же, как и в API.
Этот простой случай работает нормально — изменения, внесенные моим SUT API, успешно откатываются путем вызова _scope.Dispose(), и БД возвращается в исходное состояние. «чистое» состояние.

Проблема

Теперь я хочу переместить логику, связанную с созданием/откатом области, за пределы моего метода тестирования и поместить ее в SetUp/TearDown, чтобы все мои тесты обрабатывались автоматически.

Код: Выделить всё

[SetUp]
public async Task SetupTest()
{
_scope = TransactionHelper.CreateScope();
}

[TearDown]
public async Task TeardownTest()
{
_scope.Dispose();
_scope = null;
}

[Test]
public async Task Test11()
{
var result = await OneTimeTestFixtureStartup.Client.GetAsync("api/values?dataName1=Name1&dataName2=Name2");
Assert.DoesNotThrow(() => result.EnsureSuccessStatusCode());
}
Но по какой-то причине это НЕ работает (я вижу изменения в БД после запуска теста) и не могу этого понять.

Почему? Что мне не хватает?

Примечание: обе версии теста проходят успешно.

Вернуться в «C#»