前面我们写了针对Application的单元测试,现在希望增加对领域层和数据访问层的单元测试。首先,需要把测试模块的公共代码抽提出来,创建一个基础模块,还要把测试类中的公共代码抽提出来,创建一个基础的测试类。我们在测试目录下,增加一个新的测试项目,名称为ZL.ApbNext.Poem.TestBase,在这个测试项目下,增加两个基础类:
using Microsoft.Extensions.DependencyInjection; using System; using System.Threading.Tasks; using Volo.Abp; using Volo.Abp.Modularity; using Volo.Abp.Testing; using Volo.Abp.Uow; namespace ZL.ApbNext.Poem.TestBase { public abstract class PoemTestBase<TStartupModule> : AbpIntegratedTest<TStartupModule> where TStartupModule : IAbpModule { protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options) { options.UseAutofac(); } protected virtual Task WithUnitOfWorkAsync(Func<Task> func) { return WithUnitOfWorkAsync(new AbpUnitOfWorkOptions(), func); } protected virtual async Task WithUnitOfWorkAsync(AbpUnitOfWorkOptions options, Func<Task> action) { using (var scope = ServiceProvider.CreateScope()) { var uowManager = scope.ServiceProvider.GetRequiredService<IUnitOfWorkManager>(); using (var uow = uowManager.Begin(options)) { await action(); await uow.CompleteAsync(); } } } protected virtual Task<TResult> WithUnitOfWorkAsync<TResult>(Func<Task<TResult>> func) { return WithUnitOfWorkAsync(new AbpUnitOfWorkOptions(), func); } protected virtual async Task<TResult> WithUnitOfWorkAsync<TResult>(AbpUnitOfWorkOptions options, Func<Task<TResult>> func) { using (var scope = ServiceProvider.CreateScope()) { var uowManager = scope.ServiceProvider.GetRequiredService<IUnitOfWorkManager>(); using (var uow = uowManager.Begin(options)) { var result = await func(); await uow.CompleteAsync(); return result; } } } } } |
模块的基础类:
using Microsoft.Extensions.DependencyInjection; using Volo.Abp; using Volo.Abp.Autofac; using Volo.Abp.Data; using Volo.Abp.Modularity; using Volo.Abp.Threading; namespace ZL.ApbNext.Poem.TestBase { [DependsOn( typeof(AbpAutofacModule), typeof(AbpTestBaseModule) )] public class PoemTestBaseModule : AbpModule { public override void OnApplicationInitialization(ApplicationInitializationContext context) { SeedTestData(context); } private static void SeedTestData(ApplicationInitializationContext context) { AsyncHelper.RunSync(async () => { using (var scope = context.ServiceProvider.CreateScope()) { await scope.ServiceProvider .GetRequiredService<IDataSeeder>() .SeedAsync(); } }); } } } |
然后,我们创建数据访问层的测试ZL.AbpNext.Poem.EF.Test,这个测试需要使用sqlite作为数据库,因此在模块中需要进行配置:
using Microsoft.Data.Sqlite; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.Extensions.DependencyInjection; using System; using System.Collections.Generic; using System.Text; using Volo.Abp; using Volo.Abp.EntityFrameworkCore; using Volo.Abp.EntityFrameworkCore.Sqlite; using Volo.Abp.Modularity; using ZL.AbpNext.Poem.EF.EntityFramework; using ZL.ApbNext.Poem.TestBase; namespace ZL.AbpNext.Poem.EF.Test { [DependsOn( typeof(PoemDataModule), typeof(PoemTestBaseModule), typeof(AbpEntityFrameworkCoreSqliteModule) )] public class PoemEFTestModule:AbpModule { private SqliteConnection _sqliteConnection; public override void ConfigureServices(ServiceConfigurationContext context) { ConfigureInMemorySqlite(context.Services); } private void ConfigureInMemorySqlite(IServiceCollection services) { _sqliteConnection = CreateDatabaseAndGetConnection(); services.Configure<AbpDbContextOptions>(options => { options.Configure(context => { context.DbContextOptions.UseSqlite(_sqliteConnection); }); }); } public override void OnApplicationShutdown(ApplicationShutdownContext context) { _sqliteConnection.Dispose(); } private static SqliteConnection CreateDatabaseAndGetConnection() { var connection = new SqliteConnection("Data Source=:memory:"); connection.Open(); var options = new DbContextOptionsBuilder<PoemDbContext>() .UseSqlite(connection) .Options; using (var context = new PoemDbContext(options)) { context.GetService<IRelationalDatabaseCreator>().CreateTables(); } return connection; } } } |
测试类从测试基类派生:
using System; using System.Collections.Generic; using System.Text; using ZL.ApbNext.Poem.TestBase; namespace ZL.AbpNext.Poem.EF.Test { public abstract class PoemEFTestBase:PoemTestBase<PoemEFTestModule> { } } |
在此基础上,可以创建具体的测试,示例如下:
using System.Threading.Tasks; using Volo.Abp.Domain.Repositories; using Xunit; using ZL.AbpNext.Poem.Core.Poems; namespace ZL.AbpNext.Poem.EF.Test { public class TestRepository: PoemEFTestBase { IRepository<Category> categoryRepository; public TestRepository() { categoryRepository = GetRequiredService<IRepository<Category>>(); } [Fact] public async Task TestAddCategory() { await WithUnitOfWorkAsync(async () => { var cate= categoryRepository.InsertAsync(new Category { CategoryName = "测试" },true); Assert.True(cate.Id > 0); }); } } } |
使用同样的方法,创建针对领域层的测试ZL.AbpNext.Poem.Core.Test并改造现有的ZL.AbpNext.Poem.Application.Test。
本文内容不用于商业目的,如涉及知识产权问题,请权利人联系51Testing小编(021-64471599-8017),我们将立即处理