From 78df9ea118b60af5787a87a1a17a8f7e1a0cada2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Tue, 26 Sep 2017 11:44:12 +0300 Subject: [PATCH] Added unit test for transaction fo EF core. --- Volo.Abp.sln | 9 +++- src/Volo.Abp/Volo/Abp/AbpApplicationBase.cs | 28 ++++++++---- ...pApplicationWithExternalServiceProvider.cs | 8 +--- ...pApplicationWithInternalServiceProvider.cs | 8 +--- src/Volo.Abp/Volo/Abp/AbpKernelModule.cs | 8 ++++ src/Volo.Abp/Volo/Abp/Modularity/AbpModule.cs | 19 +++++++- .../DefaultModuleLifecycleContributer.cs | 21 ++++++++- .../IOnPostApplicationInitialization.cs | 9 ++++ .../IOnPreApplicationInitialization.cs | 9 ++++ .../Abp/Modularity/ModuleLifecycleOptions.cs | 14 ++++++ .../Volo/Abp/Modularity/ModuleManager.cs | 18 ++++++-- .../Volo.Abp.EntityFrameworkCore.Tests.csproj | 30 +++++++++++++ .../AbpEntityFrameworkCoreTestModule.cs | 42 ++++++++++++++++++ .../EntityFrameworkCoreTestBase.cs | 12 ++++++ .../Repositories/Basic_Repository_Tests.cs | 38 ++++++++++++++++ .../EntityFrameworkCore/Transaction_Tests.cs | 43 +++++++++++++++++++ .../EntityFrameworkCore/TestAppDbContext.cs | 17 ++++++++ 17 files changed, 303 insertions(+), 30 deletions(-) create mode 100644 src/Volo.Abp/Volo/Abp/Modularity/IOnPostApplicationInitialization.cs create mode 100644 src/Volo.Abp/Volo/Abp/Modularity/IOnPreApplicationInitialization.cs create mode 100644 src/Volo.Abp/Volo/Abp/Modularity/ModuleLifecycleOptions.cs create mode 100644 test/Volo.Abp.EntityFrameworkCore.Tests/Volo.Abp.EntityFrameworkCore.Tests.csproj create mode 100644 test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/AbpEntityFrameworkCoreTestModule.cs create mode 100644 test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/EntityFrameworkCoreTestBase.cs create mode 100644 test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/Repositories/Basic_Repository_Tests.cs create mode 100644 test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/Transaction_Tests.cs create mode 100644 test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/TestApp/EntityFrameworkCore/TestAppDbContext.cs diff --git a/Volo.Abp.sln b/Volo.Abp.sln index 42fddd577f..ba6b08fe0b 100644 --- a/Volo.Abp.sln +++ b/Volo.Abp.sln @@ -136,7 +136,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.Identity.Applicati EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.Identity.Domain", "src\Volo.Abp.Identity.Domain\Volo.Abp.Identity.Domain.csproj", "{43D4005C-4F04-4128-937B-52BEAC5A113B}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Identity.Domain.Shared", "src\Volo.Abp.Identity.Domain.Shared\Volo.Abp.Identity.Domain.Shared.csproj", "{DF676F73-3FC9-46CE-909A-2D75E19982AD}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.Identity.Domain.Shared", "src\Volo.Abp.Identity.Domain.Shared\Volo.Abp.Identity.Domain.Shared.csproj", "{DF676F73-3FC9-46CE-909A-2D75E19982AD}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.EntityFrameworkCore.Tests", "test\Volo.Abp.EntityFrameworkCore.Tests\Volo.Abp.EntityFrameworkCore.Tests.csproj", "{3AF7C7F5-6513-47D4-8DD0-6E1AF14568D8}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -348,6 +350,10 @@ Global {DF676F73-3FC9-46CE-909A-2D75E19982AD}.Debug|Any CPU.Build.0 = Debug|Any CPU {DF676F73-3FC9-46CE-909A-2D75E19982AD}.Release|Any CPU.ActiveCfg = Release|Any CPU {DF676F73-3FC9-46CE-909A-2D75E19982AD}.Release|Any CPU.Build.0 = Release|Any CPU + {3AF7C7F5-6513-47D4-8DD0-6E1AF14568D8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3AF7C7F5-6513-47D4-8DD0-6E1AF14568D8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3AF7C7F5-6513-47D4-8DD0-6E1AF14568D8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3AF7C7F5-6513-47D4-8DD0-6E1AF14568D8}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -413,6 +419,7 @@ Global {40E21A35-1C66-4E89-A16E-0475011F7EFD} = {146F561E-C7B8-4166-9383-47E1BC1A2E62} {43D4005C-4F04-4128-937B-52BEAC5A113B} = {1895A5C9-50D4-4568-9A3A-14657E615A5E} {DF676F73-3FC9-46CE-909A-2D75E19982AD} = {1895A5C9-50D4-4568-9A3A-14657E615A5E} + {3AF7C7F5-6513-47D4-8DD0-6E1AF14568D8} = {37087D1B-3693-4E96-983D-A69F210BDE53} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {BB97ECF4-9A84-433F-A80B-2A3285BDD1D5} diff --git a/src/Volo.Abp/Volo/Abp/AbpApplicationBase.cs b/src/Volo.Abp/Volo/Abp/AbpApplicationBase.cs index a969b2ab97..d64e415e7f 100644 --- a/src/Volo.Abp/Volo/Abp/AbpApplicationBase.cs +++ b/src/Volo.Abp/Volo/Abp/AbpApplicationBase.cs @@ -39,6 +39,18 @@ namespace Volo.Abp Modules = LoadModules(services, options); } + public virtual void Shutdown() + { + ServiceProvider + .GetRequiredService() + .ShutdownModules(new ApplicationShutdownContext()); + } + + public virtual void Dispose() + { + + } + private IReadOnlyList LoadModules(IServiceCollection services, AbpApplicationCreationOptions options) { return services @@ -50,16 +62,14 @@ namespace Volo.Abp ); } - public virtual void Shutdown() - { - ServiceProvider - .GetRequiredService() - .ShutdownModules(new ApplicationShutdownContext()); - } - - public virtual void Dispose() + protected virtual void InitializeModules() { - + using (var scope = ServiceProvider.CreateScope()) + { + ServiceProvider + .GetRequiredService() + .InitializeModules(new ApplicationInitializationContext(scope.ServiceProvider)); + } } } } \ No newline at end of file diff --git a/src/Volo.Abp/Volo/Abp/AbpApplicationWithExternalServiceProvider.cs b/src/Volo.Abp/Volo/Abp/AbpApplicationWithExternalServiceProvider.cs index 6656baaa5b..ea846809fa 100644 --- a/src/Volo.Abp/Volo/Abp/AbpApplicationWithExternalServiceProvider.cs +++ b/src/Volo.Abp/Volo/Abp/AbpApplicationWithExternalServiceProvider.cs @@ -1,7 +1,6 @@ using System; using JetBrains.Annotations; using Microsoft.Extensions.DependencyInjection; -using Volo.Abp.Modularity; namespace Volo.Abp { @@ -25,12 +24,7 @@ namespace Volo.Abp ServiceProvider = serviceProvider; - using (var scope = ServiceProvider.CreateScope()) - { - ServiceProvider - .GetRequiredService() - .InitializeModules(new ApplicationInitializationContext(scope.ServiceProvider)); - } + InitializeModules(); } } } diff --git a/src/Volo.Abp/Volo/Abp/AbpApplicationWithInternalServiceProvider.cs b/src/Volo.Abp/Volo/Abp/AbpApplicationWithInternalServiceProvider.cs index 82c1718dd7..da27610c4a 100644 --- a/src/Volo.Abp/Volo/Abp/AbpApplicationWithInternalServiceProvider.cs +++ b/src/Volo.Abp/Volo/Abp/AbpApplicationWithInternalServiceProvider.cs @@ -1,7 +1,6 @@ using System; using JetBrains.Annotations; using Microsoft.Extensions.DependencyInjection; -using Volo.Abp.Modularity; namespace Volo.Abp { @@ -37,12 +36,7 @@ namespace Volo.Abp ServiceScope = Services.BuildServiceProviderFromFactory().CreateScope(); ServiceProvider = ServiceScope.ServiceProvider; - using (var scope = ServiceProvider.CreateScope()) - { - ServiceProvider - .GetRequiredService() - .InitializeModules(new ApplicationInitializationContext(scope.ServiceProvider)); - } + InitializeModules(); } public override void Dispose() diff --git a/src/Volo.Abp/Volo/Abp/AbpKernelModule.cs b/src/Volo.Abp/Volo/Abp/AbpKernelModule.cs index 702155a3e1..3f3e42aadf 100644 --- a/src/Volo.Abp/Volo/Abp/AbpKernelModule.cs +++ b/src/Volo.Abp/Volo/Abp/AbpKernelModule.cs @@ -37,6 +37,14 @@ namespace Volo.Abp services.AddAssemblyOf(); services.TryAddObjectAccessor(); + + services.Configure(options => + { + options.Contributers.Add(); + options.Contributers.Add(); + options.Contributers.Add(); + options.Contributers.Add(); + }); } public override void OnApplicationInitialization(ApplicationInitializationContext context) diff --git a/src/Volo.Abp/Volo/Abp/Modularity/AbpModule.cs b/src/Volo.Abp/Volo/Abp/Modularity/AbpModule.cs index fab912f73e..11f2cb3f34 100644 --- a/src/Volo.Abp/Volo/Abp/Modularity/AbpModule.cs +++ b/src/Volo.Abp/Volo/Abp/Modularity/AbpModule.cs @@ -4,7 +4,14 @@ using Microsoft.Extensions.DependencyInjection; namespace Volo.Abp.Modularity { - public abstract class AbpModule : IAbpModule, IOnApplicationInitialization, IOnApplicationShutdown, IPreConfigureServices, IPostConfigureServices + public abstract class AbpModule : + IAbpModule, + IOnPreApplicationInitialization, + IOnApplicationInitialization, + IOnPostApplicationInitialization, + IOnApplicationShutdown, + IPreConfigureServices, + IPostConfigureServices { public virtual void PreConfigureServices(IServiceCollection services) { @@ -21,11 +28,21 @@ namespace Volo.Abp.Modularity } + public virtual void OnPreApplicationInitialization(ApplicationInitializationContext context) + { + + } + public virtual void OnApplicationInitialization(ApplicationInitializationContext context) { } + public virtual void OnPostApplicationInitialization(ApplicationInitializationContext context) + { + + } + public virtual void OnApplicationShutdown(ApplicationShutdownContext context) { diff --git a/src/Volo.Abp/Volo/Abp/Modularity/DefaultModuleLifecycleContributer.cs b/src/Volo.Abp/Volo/Abp/Modularity/DefaultModuleLifecycleContributer.cs index 01d7181cbd..063fe0cf12 100644 --- a/src/Volo.Abp/Volo/Abp/Modularity/DefaultModuleLifecycleContributer.cs +++ b/src/Volo.Abp/Volo/Abp/Modularity/DefaultModuleLifecycleContributer.cs @@ -1,15 +1,34 @@ namespace Volo.Abp.Modularity { - public class DefaultModuleLifecycleContributer : ModuleLifecycleContributerBase + public class OnApplicationInitializationModuleLifecycleContributer : ModuleLifecycleContributerBase { public override void Initialize(ApplicationInitializationContext context, IAbpModule module) { (module as IOnApplicationInitialization)?.OnApplicationInitialization(context); } + } + public class OnApplicationShutdownModuleLifecycleContributer : ModuleLifecycleContributerBase + { public override void Shutdown(ApplicationShutdownContext context, IAbpModule module) { (module as IOnApplicationShutdown)?.OnApplicationShutdown(context); } } + + public class OnPreApplicationInitializationModuleLifecycleContributer : ModuleLifecycleContributerBase + { + public override void Initialize(ApplicationInitializationContext context, IAbpModule module) + { + (module as IOnPreApplicationInitialization)?.OnPreApplicationInitialization(context); + } + } + + public class OnPostApplicationInitializationModuleLifecycleContributer : ModuleLifecycleContributerBase + { + public override void Initialize(ApplicationInitializationContext context, IAbpModule module) + { + (module as IOnPostApplicationInitialization)?.OnPostApplicationInitialization(context); + } + } } \ No newline at end of file diff --git a/src/Volo.Abp/Volo/Abp/Modularity/IOnPostApplicationInitialization.cs b/src/Volo.Abp/Volo/Abp/Modularity/IOnPostApplicationInitialization.cs new file mode 100644 index 0000000000..a63def315a --- /dev/null +++ b/src/Volo.Abp/Volo/Abp/Modularity/IOnPostApplicationInitialization.cs @@ -0,0 +1,9 @@ +using JetBrains.Annotations; + +namespace Volo.Abp.Modularity +{ + public interface IOnPostApplicationInitialization + { + void OnPostApplicationInitialization([NotNull] ApplicationInitializationContext context); + } +} \ No newline at end of file diff --git a/src/Volo.Abp/Volo/Abp/Modularity/IOnPreApplicationInitialization.cs b/src/Volo.Abp/Volo/Abp/Modularity/IOnPreApplicationInitialization.cs new file mode 100644 index 0000000000..a6c30880cd --- /dev/null +++ b/src/Volo.Abp/Volo/Abp/Modularity/IOnPreApplicationInitialization.cs @@ -0,0 +1,9 @@ +using JetBrains.Annotations; + +namespace Volo.Abp.Modularity +{ + public interface IOnPreApplicationInitialization + { + void OnPreApplicationInitialization([NotNull] ApplicationInitializationContext context); + } +} \ No newline at end of file diff --git a/src/Volo.Abp/Volo/Abp/Modularity/ModuleLifecycleOptions.cs b/src/Volo.Abp/Volo/Abp/Modularity/ModuleLifecycleOptions.cs new file mode 100644 index 0000000000..75f53357b4 --- /dev/null +++ b/src/Volo.Abp/Volo/Abp/Modularity/ModuleLifecycleOptions.cs @@ -0,0 +1,14 @@ +using Volo.Abp.Collections; + +namespace Volo.Abp.Modularity +{ + public class ModuleLifecycleOptions + { + public ITypeList Contributers { get; } + + public ModuleLifecycleOptions() + { + Contributers = new TypeList(); + } + } +} diff --git a/src/Volo.Abp/Volo/Abp/Modularity/ModuleManager.cs b/src/Volo.Abp/Volo/Abp/Modularity/ModuleManager.cs index 5644693da1..005fe09cff 100644 --- a/src/Volo.Abp/Volo/Abp/Modularity/ModuleManager.cs +++ b/src/Volo.Abp/Volo/Abp/Modularity/ModuleManager.cs @@ -1,5 +1,9 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; +using System.Linq; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; using Volo.Abp.DependencyInjection; namespace Volo.Abp.Modularity @@ -12,12 +16,18 @@ namespace Volo.Abp.Modularity public ModuleManager( IModuleContainer moduleContainer, - IEnumerable lifecycleContributers, - ILogger logger) + ILogger logger, + IOptions options, + IServiceProvider serviceProvider) { _moduleContainer = moduleContainer; - _lifecycleContributers = lifecycleContributers; _logger = logger; + + _lifecycleContributers = options.Value + .Contributers + .Select(serviceProvider.GetRequiredService) + .Cast() + .ToArray(); } public void InitializeModules(ApplicationInitializationContext context) diff --git a/test/Volo.Abp.EntityFrameworkCore.Tests/Volo.Abp.EntityFrameworkCore.Tests.csproj b/test/Volo.Abp.EntityFrameworkCore.Tests/Volo.Abp.EntityFrameworkCore.Tests.csproj new file mode 100644 index 0000000000..4186fa8882 --- /dev/null +++ b/test/Volo.Abp.EntityFrameworkCore.Tests/Volo.Abp.EntityFrameworkCore.Tests.csproj @@ -0,0 +1,30 @@ + + + + netcoreapp2.0 + Volo.Abp.EntityFrameworkCore.Tests + Volo.Abp.EntityFrameworkCore.Tests + true + false + false + false + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/AbpEntityFrameworkCoreTestModule.cs b/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/AbpEntityFrameworkCoreTestModule.cs new file mode 100644 index 0000000000..7f406993c9 --- /dev/null +++ b/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/AbpEntityFrameworkCoreTestModule.cs @@ -0,0 +1,42 @@ +using Microsoft.Data.Sqlite; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.Autofac; +using Volo.Abp.Modularity; +using Volo.Abp.TestApp; +using Volo.Abp.TestApp.EntityFrameworkCore; + +namespace Volo.Abp.EntityFrameworkCore +{ + [DependsOn(typeof(AbpEntityFrameworkCoreModule))] + [DependsOn(typeof(TestAppModule))] + [DependsOn(typeof(AbpAutofacModule))] + public class AbpEntityFrameworkCoreTestModule : AbpModule + { + public override void ConfigureServices(IServiceCollection services) + { + services.AddAssemblyOf(); + + services.AddAbpDbContext(options => + { + options.WithDefaultRepositories(); + }); + + var inMemorySqlite = new SqliteConnection("Data Source=:memory:"); + inMemorySqlite.Open(); + + services.Configure(options => + { + options.Configure(context => + { + context.DbContextOptions.UseSqlite(inMemorySqlite); + }); + }); + } + + public override void OnPreApplicationInitialization(ApplicationInitializationContext context) + { + context.ServiceProvider.GetRequiredService().Database.EnsureCreated(); + } + } +} diff --git a/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/EntityFrameworkCoreTestBase.cs b/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/EntityFrameworkCoreTestBase.cs new file mode 100644 index 0000000000..b773962a16 --- /dev/null +++ b/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/EntityFrameworkCoreTestBase.cs @@ -0,0 +1,12 @@ +using Volo.Abp.TestBase; + +namespace Volo.Abp.EntityFrameworkCore +{ + public abstract class EntityFrameworkCoreTestBase : AbpIntegratedTest + { + protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options) + { + options.UseAutofac(); + } + } +} diff --git a/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/Repositories/Basic_Repository_Tests.cs b/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/Repositories/Basic_Repository_Tests.cs new file mode 100644 index 0000000000..ada013b3d9 --- /dev/null +++ b/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/Repositories/Basic_Repository_Tests.cs @@ -0,0 +1,38 @@ +using System; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; +using Shouldly; +using Volo.Abp.Domain.Repositories; +using Volo.Abp.TestApp.Domain; +using Xunit; + +namespace Volo.Abp.EntityFrameworkCore.Repositories +{ + public class Basic_Repository_Tests : EntityFrameworkCoreTestBase + { + private readonly IRepository _personRepository; + + public Basic_Repository_Tests() + { + _personRepository = ServiceProvider.GetRequiredService>(); + } + + [Fact] + public void GetList() + { + _personRepository.GetList().Any().ShouldBeTrue(); + } + + [Fact] + public async Task InsertAsync() + { + var personId = Guid.NewGuid(); + + await _personRepository.InsertAsync(new Person(personId, "Adam", 42)); + + var person = await _personRepository.FindAsync(personId); + person.ShouldNotBeNull(); + } + } +} diff --git a/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/Transaction_Tests.cs b/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/Transaction_Tests.cs new file mode 100644 index 0000000000..5c18c9a7ab --- /dev/null +++ b/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/Transaction_Tests.cs @@ -0,0 +1,43 @@ +using System; +using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; +using Shouldly; +using Volo.Abp.Domain.Repositories; +using Volo.Abp.TestApp.Domain; +using Xunit; + +namespace Volo.Abp.EntityFrameworkCore +{ + public class Transaction_Tests : EntityFrameworkCoreTestBase + { + private readonly IRepository _personRepository; + + public Transaction_Tests() + { + _personRepository = ServiceProvider.GetRequiredService>(); + } + + [Fact] + public async Task Should_Rollback_Transaction_When_An_Exception_Is_Thrown() + { + var personId = Guid.NewGuid(); + const string exceptionMessage = "thrown to rollback the transaction!"; + + try + { + await WithUnitOfWorkAsync(async () => + { + await _personRepository.InsertAsync(new Person(personId, "Adam", 42)); + throw new Exception(exceptionMessage); + }); + } + catch (Exception e) when(e.Message == exceptionMessage) + { + + } + + var person = await _personRepository.FindAsync(personId); + person.ShouldBeNull(); + } + } +} diff --git a/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/TestApp/EntityFrameworkCore/TestAppDbContext.cs b/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/TestApp/EntityFrameworkCore/TestAppDbContext.cs new file mode 100644 index 0000000000..77373a84d5 --- /dev/null +++ b/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/TestApp/EntityFrameworkCore/TestAppDbContext.cs @@ -0,0 +1,17 @@ +using Microsoft.EntityFrameworkCore; +using Volo.Abp.EntityFrameworkCore; +using Volo.Abp.TestApp.Domain; + +namespace Volo.Abp.TestApp.EntityFrameworkCore +{ + public class TestAppDbContext : AbpDbContext + { + public DbSet People { get; set; } + + public TestAppDbContext(DbContextOptions options) + : base(options) + { + + } + } +}