У меня есть 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();
}
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;
}
}
Этот простой случай работает нормально — изменения, внесенные моим 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());
}
Почему? Что мне не хватает?
Примечание: обе версии теста проходят успешно.