Browse Source
新增用户应用服务单元测试,包含创建、查询、更新和删除等功能测试。同时增加数据种子初始化测试,验证角色和用户的创建。更新EF Core测试模块,使用PostgreSQL代替内存数据库,并添加数据种子。pull/1149/head
8 changed files with 599 additions and 15 deletions
@ -0,0 +1,137 @@ |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using PackageName.CompanyName.ProjectName.AIO.EntityFrameworkCore.DataSeeder; |
|||
using PackageName.CompanyName.ProjectName.Users; |
|||
using Shouldly; |
|||
using System; |
|||
using System.Linq; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.Data; |
|||
using Volo.Abp.Domain.Repositories; |
|||
using Volo.Abp.Identity; |
|||
using Volo.Abp.Uow; |
|||
using Xunit; |
|||
|
|||
namespace PackageName.CompanyName.ProjectName.DataSeeder |
|||
{ |
|||
/// <summary>
|
|||
/// 数据种子初始化测试
|
|||
/// </summary>
|
|||
[Collection("Database")] |
|||
public class ProjectNameDataSeederTests : ProjectNameApplicationTestBase |
|||
{ |
|||
private readonly IProjectNameDataSeeder _inspectionDataSeeder; |
|||
private readonly IRepository<User, Guid> _userRepository; |
|||
private readonly IIdentityRoleRepository _identityRoleRepository; |
|||
private readonly IIdentityUserRepository _identityUserRepository; |
|||
|
|||
public ProjectNameDataSeederTests() |
|||
{ |
|||
_inspectionDataSeeder = GetRequiredService<IProjectNameDataSeeder>(); |
|||
_userRepository = GetRequiredService<IRepository<User, Guid>>(); |
|||
_identityRoleRepository = GetRequiredService<IIdentityRoleRepository>(); |
|||
_identityUserRepository = GetRequiredService<IIdentityUserRepository>(); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_Seed_Data_Successfully() |
|||
{ |
|||
// Arrange
|
|||
var context = new DataSeedContext(); |
|||
|
|||
// Act
|
|||
await _inspectionDataSeeder.SeedAsync(context); |
|||
|
|||
// Assert - 使用单元工作方法包装所有数据库操作
|
|||
await WithUnitOfWorkAsync(async () => |
|||
{ |
|||
// 测试角色
|
|||
var roles = await _identityRoleRepository.GetListAsync(); |
|||
roles.Count.ShouldBeGreaterThanOrEqualTo(7); // 至少应该有 7 个角色
|
|||
|
|||
var superAdminRole = await _identityRoleRepository.FindByNormalizedNameAsync("超级管理员".ToUpperInvariant()); |
|||
superAdminRole.ShouldNotBeNull(); |
|||
// 测试用户
|
|||
var users = await _userRepository.GetListAsync(); |
|||
users.Count.ShouldBeGreaterThanOrEqualTo(10); // 至少应该有 10 个用户
|
|||
|
|||
foreach (var user in users) |
|||
{ |
|||
user.IdentityUserId.ShouldNotBe(Guid.Empty); |
|||
|
|||
var identityUser = await _identityUserRepository.GetAsync(user.IdentityUserId); |
|||
identityUser.ShouldNotBeNull(); |
|||
} |
|||
|
|||
return true; |
|||
}); |
|||
} |
|||
|
|||
[Theory] |
|||
[InlineData("超级管理员")] |
|||
[InlineData("普通用户")] |
|||
public async Task Should_Create_Roles(string roleName) |
|||
{ |
|||
// Arrange
|
|||
var context = new DataSeedContext(); |
|||
await _inspectionDataSeeder.SeedAsync(context); |
|||
|
|||
// Act & Assert - 使用单元工作方法包装
|
|||
await WithUnitOfWorkAsync(async () => |
|||
{ |
|||
var role = await _identityRoleRepository.FindByNormalizedNameAsync(roleName.ToUpperInvariant()); |
|||
role.ShouldNotBeNull(); |
|||
role.Name.ShouldBe(roleName); |
|||
|
|||
return true; |
|||
}); |
|||
} |
|||
|
|||
[Theory] |
|||
[InlineData("testuser1")] |
|||
[InlineData("testuser2")] |
|||
public async Task Should_Create_Users(string nickName) |
|||
{ |
|||
// Arrange
|
|||
var context = new DataSeedContext(); |
|||
await _inspectionDataSeeder.SeedAsync(context); |
|||
|
|||
// Act & Assert - 使用单元工作方法包装
|
|||
await WithUnitOfWorkAsync(async () => |
|||
{ |
|||
var users = await _userRepository.GetListAsync(); |
|||
var user = users.FirstOrDefault(u => u.NickName == nickName); |
|||
user.ShouldNotBeNull(); |
|||
user.NickName.ShouldBe(nickName); |
|||
user.IdentityUserId.ShouldNotBe(Guid.Empty); |
|||
|
|||
var identityUser = await _identityUserRepository.GetAsync(user.IdentityUserId); |
|||
identityUser.ShouldNotBeNull(); |
|||
identityUser.Name.ShouldBe(nickName); |
|||
|
|||
return true; |
|||
}); |
|||
} |
|||
|
|||
// 添加单元工作方法
|
|||
protected override Task<TResult> WithUnitOfWorkAsync<TResult>(Func<Task<TResult>> func) |
|||
{ |
|||
return WithUnitOfWorkAsync(new AbpUnitOfWorkOptions(), func); |
|||
} |
|||
|
|||
// 可选:添加重载方法以支持更多场景
|
|||
protected async override 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; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -1,11 +1,63 @@ |
|||
using Hangfire; |
|||
using Hangfire.MemoryStorage; |
|||
using LINGYUN.Abp.Identity; |
|||
using LINGYUN.Abp.Identity.Session; |
|||
using Microsoft.AspNetCore.Identity; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Microsoft.Extensions.FileProviders; |
|||
using Microsoft.Extensions.Hosting; |
|||
using Microsoft.Extensions.Logging; |
|||
using Microsoft.Extensions.Logging.Abstractions; |
|||
using PackageName.CompanyName.ProjectName.AIO.EntityFrameworkCore.DataSeeder; |
|||
using PackageName.CompanyName.ProjectName.EntityFrameworkCore; |
|||
using Volo.Abp.Modularity; |
|||
using Volo.Abp.PermissionManagement.Identity; |
|||
using Volo.Abp.Security.Claims; |
|||
|
|||
namespace PackageName.CompanyName.ProjectName; |
|||
|
|||
[DependsOn( |
|||
typeof(ProjectNameDomainTestModule), |
|||
typeof(ProjectNameApplicationModule) |
|||
typeof(ProjectNameApplicationModule), |
|||
typeof(AbpIdentityApplicationModule), |
|||
typeof(AbpPermissionManagementDomainIdentityModule), |
|||
typeof(ProjectNameEntityFrameworkCoreTestModule) |
|||
)] |
|||
public class ProjectNameApplicationTestModule : AbpModule |
|||
{ |
|||
public override void ConfigureServices(ServiceConfigurationContext context) |
|||
{ |
|||
// //设置ILogger为NullLogger
|
|||
context.Services.AddLogging(builder => builder.AddProvider(NullLoggerProvider.Instance)); |
|||
context.Services.AddTransient<IProjectNameDataSeeder, ProjectNameDataSeeder>(); |
|||
context.Services.AddLogging(builder => builder.AddProvider(NullLoggerProvider.Instance)); |
|||
context.Services.AddTransient<IHostEnvironment, TestHostEnvironment>(); |
|||
context.Services.AddTransient<IFileProvider, TestFileProvider>(); |
|||
|
|||
// 增加配置文件定义,在新建租户时需要
|
|||
Configure<IdentityOptions>(options => |
|||
{ |
|||
// 允许中文用户名
|
|||
options.User.AllowedUserNameCharacters = null; |
|||
// 支持弱密码
|
|||
options.Password.RequireDigit = false; |
|||
options.Password.RequiredLength = 1; |
|||
options.Password.RequireLowercase = false; |
|||
options.Password.RequireNonAlphanumeric = false; |
|||
options.Password.RequireUppercase = false; |
|||
}); |
|||
Configure<AbpClaimsPrincipalFactoryOptions>(options => |
|||
{ |
|||
options.IsDynamicClaimsEnabled = true; |
|||
}); |
|||
Configure<IdentitySessionCleanupOptions>(options => |
|||
{ |
|||
options.IsCleanupEnabled = true; |
|||
}); |
|||
// 配置Hangfire
|
|||
context.Services.AddHangfire(config => |
|||
{ |
|||
config.UseMemoryStorage(); |
|||
}); |
|||
} |
|||
} |
|||
|
|||
@ -0,0 +1,64 @@ |
|||
using Microsoft.Extensions.FileProviders; |
|||
using Microsoft.Extensions.Primitives; |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.IO; |
|||
|
|||
namespace PackageName.CompanyName.ProjectName; |
|||
|
|||
public class TestFileProvider : IFileProvider |
|||
{ |
|||
private readonly Dictionary<string, IFileInfo> _files; |
|||
|
|||
public TestFileProvider() |
|||
{ |
|||
_files = new Dictionary<string, IFileInfo>(); |
|||
} |
|||
|
|||
public IDirectoryContents GetDirectoryContents(string subpath) |
|||
{ |
|||
return new NotFoundDirectoryContents(); |
|||
} |
|||
|
|||
public IFileInfo GetFileInfo(string subpath) |
|||
{ |
|||
if (_files.TryGetValue(subpath, out var fileInfo)) |
|||
{ |
|||
return fileInfo; |
|||
} |
|||
return new NotFoundFileInfo(subpath); |
|||
} |
|||
|
|||
public IChangeToken Watch(string filter) |
|||
{ |
|||
return NullChangeToken.Singleton; |
|||
} |
|||
|
|||
public void AddFile(string path, string contents) |
|||
{ |
|||
_files[path] = new TestFileInfo(path, contents); |
|||
} |
|||
} |
|||
|
|||
public class TestFileInfo : IFileInfo |
|||
{ |
|||
private readonly string _contents; |
|||
|
|||
public TestFileInfo(string name, string contents) |
|||
{ |
|||
Name = name; |
|||
_contents = contents; |
|||
} |
|||
|
|||
public bool Exists => true; |
|||
public long Length => _contents.Length; |
|||
public string PhysicalPath => null; |
|||
public string Name { get; } |
|||
public DateTimeOffset LastModified => DateTimeOffset.UtcNow; |
|||
public bool IsDirectory => false; |
|||
|
|||
public Stream CreateReadStream() |
|||
{ |
|||
return new MemoryStream(System.Text.Encoding.UTF8.GetBytes(_contents)); |
|||
} |
|||
} |
|||
@ -0,0 +1,21 @@ |
|||
using Microsoft.Extensions.FileProviders; |
|||
using Microsoft.Extensions.Hosting; |
|||
using System; |
|||
|
|||
namespace PackageName.CompanyName.ProjectName; |
|||
|
|||
public class TestHostEnvironment : IHostEnvironment |
|||
{ |
|||
public TestHostEnvironment() |
|||
{ |
|||
EnvironmentName = "Test"; |
|||
ApplicationName = "TestApplication"; |
|||
ContentRootPath = AppDomain.CurrentDomain.BaseDirectory; |
|||
ContentRootFileProvider = new PhysicalFileProvider(ContentRootPath); |
|||
} |
|||
|
|||
public string EnvironmentName { get; set; } |
|||
public string ApplicationName { get; set; } |
|||
public string ContentRootPath { get; set; } |
|||
public IFileProvider ContentRootFileProvider { get; set; } |
|||
} |
|||
@ -0,0 +1,265 @@ |
|||
using PackageName.CompanyName.ProjectName.Users.Dtos; |
|||
using Shouldly; |
|||
using System; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.Domain.Entities; |
|||
using Volo.Abp.Validation; |
|||
using Xunit; |
|||
|
|||
namespace PackageName.CompanyName.ProjectName.Users |
|||
{ |
|||
/// <summary>
|
|||
/// UserAppService 的单元测试
|
|||
/// </summary>
|
|||
[Collection("Database")] |
|||
public class UserAppServiceTests : ProjectNameApplicationTestBase |
|||
{ |
|||
private readonly IUserAppService _userAppService; |
|||
private readonly IUserManager _userManager; |
|||
|
|||
public UserAppServiceTests() |
|||
{ |
|||
_userAppService = GetRequiredService<IUserAppService>(); |
|||
_userManager = GetRequiredService<IUserManager>(); |
|||
} |
|||
|
|||
[Theory] |
|||
[InlineData("testuser1", "Test123456!", true)] |
|||
[InlineData("testuser2", "Test123456!", false)] |
|||
public async Task Should_Create_User( |
|||
string nickName, |
|||
string password, |
|||
bool isActive) |
|||
{ |
|||
// Arrange
|
|||
var input = new CreateUpdateUserDto |
|||
{ |
|||
NickName = nickName, |
|||
Password = password, |
|||
IsActive = isActive |
|||
}; |
|||
|
|||
// Act
|
|||
var result = await _userAppService.CreateAsync(input); |
|||
|
|||
// Assert
|
|||
result.ShouldNotBeNull(); |
|||
result.NickName.ShouldBe(nickName); |
|||
result.IsActive.ShouldBe(isActive); |
|||
} |
|||
|
|||
[Theory] |
|||
[InlineData("", "Test123456!", "用户名称不能为空")] |
|||
[InlineData("test", "123", "密码长度必须在6-20个字符之间")] |
|||
public async Task Should_Not_Create_User_With_Invalid_Input(string nickName, string password, |
|||
string expectedErrorMessage) |
|||
{ |
|||
// Arrange
|
|||
var input = new CreateUpdateUserDto |
|||
{ |
|||
NickName = nickName, |
|||
Password = password |
|||
}; |
|||
|
|||
// Act & Assert
|
|||
var exception = await Assert.ThrowsAsync<AbpValidationException>(async () => |
|||
{ |
|||
await _userAppService.CreateAsync(input); |
|||
}); |
|||
|
|||
exception.ValidationErrors.ShouldContain(x => x.ErrorMessage.Contains(expectedErrorMessage)); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_Get_User_List() |
|||
{ |
|||
// Arrange
|
|||
await CreateTestUserAsync("testuser1", "Test123456!"); |
|||
await CreateTestUserAsync("testuser2", "Test123456!"); |
|||
|
|||
// Act
|
|||
var result = await _userAppService.GetListAsync( |
|||
new UserPagedAndSortedResultRequestDto |
|||
{ |
|||
MaxResultCount = 10, |
|||
SkipCount = 0, |
|||
Sorting = "NickName" |
|||
}); |
|||
|
|||
// Assert
|
|||
result.ShouldNotBeNull(); |
|||
result.TotalCount.ShouldBeGreaterThanOrEqualTo(2); |
|||
result.Items.ShouldContain(x => x.NickName == "testuser1"); |
|||
result.Items.ShouldContain(x => x.NickName == "testuser2"); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_Filter_Users_By_NickName() |
|||
{ |
|||
// Arrange
|
|||
await CreateTestUserAsync("testuser1", "Test123456!"); |
|||
await CreateTestUserAsync("testuser2", "Test123456!"); |
|||
await CreateTestUserAsync("otheruser", "Test123456!"); |
|||
|
|||
// Act
|
|||
var result = await _userAppService.GetListAsync( |
|||
new UserPagedAndSortedResultRequestDto |
|||
{ |
|||
MaxResultCount = 10, |
|||
SkipCount = 0, |
|||
Sorting = "NickName", |
|||
NickName = "testuser" |
|||
}); |
|||
|
|||
// Assert
|
|||
result.ShouldNotBeNull(); |
|||
result.TotalCount.ShouldBe(2); |
|||
result.Items.ShouldContain(x => x.NickName == "testuser1"); |
|||
result.Items.ShouldContain(x => x.NickName == "testuser2"); |
|||
result.Items.ShouldNotContain(x => x.NickName == "otheruser"); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_Update_User() |
|||
{ |
|||
// Arrange
|
|||
var user = await CreateTestUserAsync("updatetest", "Test123456!"); |
|||
var updateInput = new CreateUpdateUserDto |
|||
{ |
|||
NickName = "updateduser", |
|||
Password = "NewPassword123!", |
|||
ContactInfo = "13800138000", |
|||
Position = "开发工程师", |
|||
IsActive = true |
|||
}; |
|||
|
|||
// Act
|
|||
var result = await _userAppService.UpdateAsync(user.Id, updateInput); |
|||
|
|||
// Assert
|
|||
result.ShouldNotBeNull(); |
|||
result.NickName.ShouldBe("updateduser"); |
|||
result.ContactInfo.ShouldBe("13800138000"); |
|||
result.Position.ShouldBe("开发工程师"); |
|||
|
|||
// 验证更新后的用户信息
|
|||
var updatedUser = await _userAppService.GetAsync(user.Id); |
|||
updatedUser.NickName.ShouldBe("updateduser"); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_Not_Update_Non_Existing_User() |
|||
{ |
|||
// Arrange
|
|||
var input = new CreateUpdateUserDto |
|||
{ |
|||
NickName = "testuser", |
|||
Password = "Test123456!" |
|||
}; |
|||
|
|||
// Act & Assert
|
|||
await Assert.ThrowsAsync<EntityNotFoundException>(async () => |
|||
{ |
|||
await _userAppService.UpdateAsync(Guid.NewGuid(), input); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_Delete_User() |
|||
{ |
|||
// Arrange
|
|||
var user = await CreateTestUserAsync("deletetest", "Test123456!"); |
|||
|
|||
// Act
|
|||
await _userAppService.DeleteAsync(user.Id); |
|||
|
|||
// Assert - 尝试获取已删除的用户应该抛出异常
|
|||
await Assert.ThrowsAsync<EntityNotFoundException>(async () => |
|||
{ |
|||
await _userAppService.GetAsync(user.Id); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_Change_User_Password() |
|||
{ |
|||
// Arrange
|
|||
var user = await CreateTestUserAsync("passwordtest", "OldPassword123!"); |
|||
|
|||
// Act & Assert
|
|||
await _userAppService.ChangePasswordAsync(user.Id, "OldPassword123!", "NewPassword123!"); |
|||
|
|||
// 尝试用新密码登录(这个需要集成测试才能完整测试)
|
|||
// 这里我们只是验证方法执行不会抛出异常
|
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_Reset_User_Password() |
|||
{ |
|||
// Arrange
|
|||
var user = await CreateTestUserAsync("resetpasswordtest", "OldPassword123!"); |
|||
|
|||
// Act & Assert
|
|||
await _userAppService.ResetPasswordAsync(user.Id, "NewPassword123!"); |
|||
|
|||
// 同样,完整测试需要验证用户能用新密码登录,这需要集成测试
|
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_Set_User_Active_Status() |
|||
{ |
|||
// Arrange
|
|||
var user = await CreateTestUserAsync("activestatustest", "Password123!"); |
|||
|
|||
// Act
|
|||
await _userAppService.SetUserActiveStatusAsync(user.Id, false); |
|||
var disabledUser = await _userAppService.GetAsync(user.Id); |
|||
|
|||
await _userAppService.SetUserActiveStatusAsync(user.Id, true); |
|||
var enabledUser = await _userAppService.GetAsync(user.Id); |
|||
|
|||
// Assert
|
|||
disabledUser.IsActive.ShouldBeFalse(); |
|||
enabledUser.IsActive.ShouldBeTrue(); |
|||
} |
|||
|
|||
[Theory] |
|||
[InlineData("13900000000", "工程师")] |
|||
[InlineData("13800000000", "设计师")] |
|||
[InlineData(null, null)] |
|||
public async Task Should_Create_User_With_Optional_Fields(string contactInfo, string position) |
|||
{ |
|||
// Arrange
|
|||
var input = new CreateUpdateUserDto |
|||
{ |
|||
NickName = $"user_{Guid.NewGuid():N}", |
|||
Password = "Test123456!", |
|||
ContactInfo = contactInfo, |
|||
Position = position |
|||
}; |
|||
|
|||
// Act
|
|||
var result = await _userAppService.CreateAsync(input); |
|||
|
|||
// Assert
|
|||
result.ShouldNotBeNull(); |
|||
result.ContactInfo.ShouldBe(contactInfo); |
|||
result.Position.ShouldBe(position); |
|||
} |
|||
|
|||
private async Task<UserDto> CreateTestUserAsync(string nickName, string password) |
|||
{ |
|||
return await WithUnitOfWorkAsync(async () => |
|||
{ |
|||
var input = new CreateUpdateUserDto |
|||
{ |
|||
NickName = nickName, |
|||
Password = password, |
|||
IsActive = true |
|||
}; |
|||
|
|||
return await _userAppService.CreateAsync(input); |
|||
}); |
|||
} |
|||
} |
|||
} |
|||
@ -1,38 +1,74 @@ |
|||
using Microsoft.EntityFrameworkCore; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using PackageName.CompanyName.ProjectName.AIO.EntityFrameworkCore; |
|||
using System; |
|||
using Volo.Abp; |
|||
using Volo.Abp.Data; |
|||
using Volo.Abp.EntityFrameworkCore; |
|||
using Volo.Abp.Modularity; |
|||
using Volo.Abp.Threading; |
|||
using Volo.Abp.Timing; |
|||
using Volo.Abp.Uow; |
|||
|
|||
namespace PackageName.CompanyName.ProjectName.EntityFrameworkCore; |
|||
|
|||
[DependsOn( |
|||
typeof(ProjectNameTestBaseModule), |
|||
typeof(ProjectNameEntityFrameworkCoreModule) |
|||
)] |
|||
typeof(ProjectNameEntityFrameworkCoreModule), |
|||
typeof(SingleMigrationsEntityFrameworkCoreModule) |
|||
)] |
|||
public class ProjectNameEntityFrameworkCoreTestModule : AbpModule |
|||
{ |
|||
// 数据库配置
|
|||
private const string DefaultPostgresConnectionString = |
|||
"Host=127.0.0.1;Port=5432;Database=test_db;User Id=postgres;Password=postgres;"; |
|||
|
|||
public override void ConfigureServices(ServiceConfigurationContext context) |
|||
{ |
|||
context.Services.AddEntityFrameworkInMemoryDatabase(); |
|||
var connectionString = Environment.GetEnvironmentVariable("TEST_CONNECTION_STRING") ?? |
|||
DefaultPostgresConnectionString; |
|||
|
|||
var databaseName = Guid.NewGuid().ToString(); |
|||
// 配置数据库连接字符串
|
|||
Configure<AbpDbConnectionOptions>(options => |
|||
{ |
|||
options.ConnectionStrings.Default = connectionString; |
|||
}); |
|||
|
|||
Configure<AbpDbContextOptions>(options => |
|||
Configure<AbpClockOptions>(options => { options.Kind = DateTimeKind.Utc; }); |
|||
context.Services.AddAbpDbContext<SingleMigrationsDbContext>(options => |
|||
{ |
|||
options.Configure(abpDbContextConfigurationContext => |
|||
{ |
|||
abpDbContextConfigurationContext.DbContextOptions.EnableDetailedErrors(); |
|||
abpDbContextConfigurationContext.DbContextOptions.EnableSensitiveDataLogging(); |
|||
options.AddDefaultRepositories(true); |
|||
}); |
|||
|
|||
abpDbContextConfigurationContext.DbContextOptions.UseInMemoryDatabase(databaseName); |
|||
}); |
|||
// 配置所有DbContext
|
|||
Configure<AbpDbContextOptions>(options => |
|||
{ |
|||
AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true); |
|||
options.UseNpgsql(); |
|||
}); |
|||
|
|||
Configure<AbpUnitOfWorkDefaultOptions>(options => |
|||
{ |
|||
options.TransactionBehavior = UnitOfWorkTransactionBehavior.Disabled; //EF in-memory database does not support transactions
|
|||
options.TransactionBehavior = UnitOfWorkTransactionBehavior.Disabled; |
|||
}); |
|||
} |
|||
} |
|||
|
|||
public override void OnPreApplicationInitialization(ApplicationInitializationContext context) |
|||
{ |
|||
var dbContext = context.ServiceProvider.GetRequiredService<SingleMigrationsDbContext>(); |
|||
// 重置数据库
|
|||
dbContext.Database.EnsureDeleted(); |
|||
// // 创建数据库
|
|||
dbContext.Database.EnsureCreated(); |
|||
dbContext.Database.GenerateCreateScript(); |
|||
// dbContext.Database.Migrate();
|
|||
|
|||
// 初始化种子数据
|
|||
var dataSeeder = context.ServiceProvider.GetRequiredService<IDataSeeder>(); |
|||
AsyncHelper.RunSync(() => dataSeeder.SeedAsync()); |
|||
} |
|||
|
|||
public override void OnApplicationShutdown(ApplicationShutdownContext context) |
|||
{ |
|||
} |
|||
} |
|||
Loading…
Reference in new issue