Сценарий
У меня есть API на ASP. NET Core 2.0, который интегрируется с базой данных MS SQL с использованием EF Core. Сейчас я пытаюсь настроить интеграционные / API-тесты для него, используя NUnit и TestServer
. Проблема в том, что мне нужно настроить каждый тест как «изолированный», так что в основном он должен очищать (откатывать) БД после самостоятельной работы. Я не могу использовать компенсационные транзакции для достижения желаемого результата из-за сложности БД (множество унаследованных вещей, например, триггеров и т. Д. c).
Настройка API SUT
Здесь пример API, который я пытаюсь протестировать:
// GET api/values
[HttpGet]
public async Task<IActionResult> 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;
}
}
Здесь Client
является экземпляром HttpClient
созданный с использованием методов Microsoft.AspNetCore.TestHost.TestServer
и CreateScope()
фактически такой же, как в API. Этот простой случай работает нормально - изменения, сделанные моим SUT API, успешно откатываются путем вызова _scope.Dispose()
и DB возвращается в свое «чистое» состояние.
Проблема
Теперь я хочу переместить logi c относится к созданию / откату области действия вне моего метода тестирования и помещает его в 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());
}
Но это НЕ работает (я вижу изменения в БД после пробного запуска) по какой то причине и не могу разобраться.
Почему? Чего мне не хватает?
Примечание: обе версии теста пройдены успешно.