Broke all our test cases: Abp.AbpException : Did not call Complete method of a unit of work.....
See original GitHub issueHi Halil,
- ABP 2.1.2
We have been running ABP in our unit tests as follows for a long time now, but this behavior started happening as soon as we upgraded from 2.0 to 2.1.2. And unfortunately rolling back is not an option at the moment so I am looking for a fix or work around ASAP.
We use NUnit for all our unit testing and have our test fixtures structured as follows:
/// <summary>
/// Adapter class to work with the ABP base test class, to ensure the IocManager is correctly
/// instantiated.
/// </summary>
public class AbpApplicationServiceTestsAdapter : OzAbpTestsAdapterBase<AbpApplicationServiceTestsAdapterModule>
{
/// <summary>
/// Class constructor.
/// </summary>
public AbpApplicationServiceTestsAdapter()
{
//Ensure all the AutoMapper mappings are in place
OzCpAutoMapperConfig autoMapperConfig = new OzCpAutoMapperConfig();
autoMapperConfig.Configure();
//Ensure that we have applied all the DB migrations
string connString = ConfigurationManager.ConnectionStrings["Default"].ConnectionString;
DatabaseMigrationsManager dbMigrationsManager = new DatabaseMigrationsManager(connString, DbEnvironmentKindEnum.Automation);
DatabaseUpgradeResult dbMigrationResult = dbMigrationsManager.Process();
if (!dbMigrationResult.Successful)
throw dbMigrationResult.Error;
}
}
[TestFixture]
public class OzCpApiServiceTests : OzTestsBase
{
private AbpApplicationServiceTestsAdapter _AbpApplicationTestsAdapter;
private IOzCpApiService _ApiService;
private IUnitOfWorkCompleteHandle _UnitOfWork;
private IUnitOfWorkManager _UnitOfWorkManager;
/// <summary>
/// Called at the conclusion of all the unit tests.
/// </summary>
[OneTimeTearDown]
public void DeInit()
{
}
/// <summary>
/// Called at the commencement of all the unit tests.
/// </summary>
[OneTimeSetUp]
public void Init()
{
//Spin up the adapter class to register all the necessary with the IocManager
_AbpApplicationTestsAdapter = new AbpApplicationServiceTestsAdapter();
//Create our reference to the reference port service
_ApiService = _AbpApplicationTestsAdapter.LocalIocManager.Resolve<IOzCpApiService>();
}
/// <summary>
/// Called before each test.
/// </summary>
[SetUp]
public void TestSetup()
{
//Ensure all interactions run within a transaction of their own so that our changes are not persisted to the test database
_UnitOfWorkManager = _AbpApplicationTestsAdapter.LocalIocManager.Resolve<IUnitOfWorkManager>();
_UnitOfWork = _UnitOfWorkManager.Begin(new UnitOfWorkOptions
{
IsolationLevel = IsolationLevel.ReadUncommitted
});
}
/// <summary>
/// Called after each test.
/// </summary>
[TearDown]
public void TestTearDown()
{
//Clean up any manually resolved IoC instances
_AbpApplicationTestsAdapter.LocalIocManager.Release(_ApiService);
//Force our unit of work to roll back our transaction
_UnitOfWork.Dispose();
}
}
You can pretty much ignore the AbpApplicationServiceTestsAdapter asit just ensures that the AbpApplicationServiceTestsAdapterModule pulls in all the required ABP modules which ulitmately contain the services and repositories.
In essence our tests all run against a physical SQL Server database (we cannot mock as we need SP support etc.) but we make sure that each test runs within its own transaction. However today when running our unit tests I started getting:
TearDown : Abp.AbpException : Did not call Complete method of a unit of work. –TearDown at Abp.Domain.Uow.InnerUnitOfWorkCompleteHandle.Dispose()
So what this has meant is that transactions are not working as expected and I have data changes occurring in our Test DB when they should have been rolled back. I am also getting similair timeout issues as reported in #2217 but I figured that was related to my error above.
So can you advise whether:
- We have uncovered a bug? (We specifically don’t call .Complete() as we want to roll back the transaction)
- If not a bug then how I should deal with transactions for each test case so that it works “with ABP”?
Issue Analytics
- State:
- Created 6 years ago
- Comments:31 (31 by maintainers)
Top GitHub Comments
The problem is tricky and related to implementation of AsyncLocal by .net. If you want to know more, you can read this issue (https://github.com/dotnet/corefx/issues/8681) which I have some comments and code samples.
In brief, if you set an ambient value (to callcontext or asynclocal) and return from the method, the value has gone! You begin UOW inside TestSetup then returning from this method and ambient UOW reference is lost. I know this is a strange behaviour and I could not find a way and Microsoft workers said this is by design. Anyway, after the test I requested, we can better understand if the problem is that.
It can be related to AsyncLocal change but really I could not figure out what’s the exact difference.