diff --git a/aspnet-core/templates/aio/content/tests/PackageName.CompanyName.ProjectName.Application.Tests/PackageName.CompanyName.ProjectName.Application.Tests.csproj b/aspnet-core/templates/aio/content/tests/PackageName.CompanyName.ProjectName.Application.Tests/PackageName.CompanyName.ProjectName.Application.Tests.csproj
index a661f6026..938edc57b 100644
--- a/aspnet-core/templates/aio/content/tests/PackageName.CompanyName.ProjectName.Application.Tests/PackageName.CompanyName.ProjectName.Application.Tests.csproj
+++ b/aspnet-core/templates/aio/content/tests/PackageName.CompanyName.ProjectName.Application.Tests/PackageName.CompanyName.ProjectName.Application.Tests.csproj
@@ -7,12 +7,17 @@
+
+
+
+
+
diff --git a/aspnet-core/templates/aio/content/tests/PackageName.CompanyName.ProjectName.Application.Tests/PackageName/CompanyName/ProjectName/DataSeeder/ProjectNameDataSeederTests.cs b/aspnet-core/templates/aio/content/tests/PackageName.CompanyName.ProjectName.Application.Tests/PackageName/CompanyName/ProjectName/DataSeeder/ProjectNameDataSeederTests.cs
new file mode 100644
index 000000000..dd8ff6727
--- /dev/null
+++ b/aspnet-core/templates/aio/content/tests/PackageName.CompanyName.ProjectName.Application.Tests/PackageName/CompanyName/ProjectName/DataSeeder/ProjectNameDataSeederTests.cs
@@ -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
+{
+ ///
+ /// 数据种子初始化测试
+ ///
+ [Collection("Database")]
+ public class ProjectNameDataSeederTests : ProjectNameApplicationTestBase
+ {
+ private readonly IProjectNameDataSeeder _inspectionDataSeeder;
+ private readonly IRepository _userRepository;
+ private readonly IIdentityRoleRepository _identityRoleRepository;
+ private readonly IIdentityUserRepository _identityUserRepository;
+
+ public ProjectNameDataSeederTests()
+ {
+ _inspectionDataSeeder = GetRequiredService();
+ _userRepository = GetRequiredService>();
+ _identityRoleRepository = GetRequiredService();
+ _identityUserRepository = GetRequiredService();
+ }
+
+ [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 WithUnitOfWorkAsync(Func> func)
+ {
+ return WithUnitOfWorkAsync(new AbpUnitOfWorkOptions(), func);
+ }
+
+ // 可选:添加重载方法以支持更多场景
+ protected async override Task WithUnitOfWorkAsync(AbpUnitOfWorkOptions options, Func> func)
+ {
+ using (var scope = ServiceProvider.CreateScope())
+ {
+ var uowManager = scope.ServiceProvider.GetRequiredService();
+
+ using (var uow = uowManager.Begin(options))
+ {
+ var result = await func();
+ await uow.CompleteAsync();
+ return result;
+ }
+ }
+ }
+ }
+}
diff --git a/aspnet-core/templates/aio/content/tests/PackageName.CompanyName.ProjectName.Application.Tests/PackageName/CompanyName/ProjectName/ProjectNameApplicationTestModule.cs b/aspnet-core/templates/aio/content/tests/PackageName.CompanyName.ProjectName.Application.Tests/PackageName/CompanyName/ProjectName/ProjectNameApplicationTestModule.cs
index 7e9fa658a..e07d40f8e 100644
--- a/aspnet-core/templates/aio/content/tests/PackageName.CompanyName.ProjectName.Application.Tests/PackageName/CompanyName/ProjectName/ProjectNameApplicationTestModule.cs
+++ b/aspnet-core/templates/aio/content/tests/PackageName.CompanyName.ProjectName.Application.Tests/PackageName/CompanyName/ProjectName/ProjectNameApplicationTestModule.cs
@@ -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();
+ context.Services.AddLogging(builder => builder.AddProvider(NullLoggerProvider.Instance));
+ context.Services.AddTransient();
+ context.Services.AddTransient();
+
+ // 增加配置文件定义,在新建租户时需要
+ Configure(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(options =>
+ {
+ options.IsDynamicClaimsEnabled = true;
+ });
+ Configure(options =>
+ {
+ options.IsCleanupEnabled = true;
+ });
+ // 配置Hangfire
+ context.Services.AddHangfire(config =>
+ {
+ config.UseMemoryStorage();
+ });
+ }
}
diff --git a/aspnet-core/templates/aio/content/tests/PackageName.CompanyName.ProjectName.Application.Tests/PackageName/CompanyName/ProjectName/TestFileProvider.cs b/aspnet-core/templates/aio/content/tests/PackageName.CompanyName.ProjectName.Application.Tests/PackageName/CompanyName/ProjectName/TestFileProvider.cs
new file mode 100644
index 000000000..c7a075cb2
--- /dev/null
+++ b/aspnet-core/templates/aio/content/tests/PackageName.CompanyName.ProjectName.Application.Tests/PackageName/CompanyName/ProjectName/TestFileProvider.cs
@@ -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 _files;
+
+ public TestFileProvider()
+ {
+ _files = new Dictionary();
+ }
+
+ 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));
+ }
+}
\ No newline at end of file
diff --git a/aspnet-core/templates/aio/content/tests/PackageName.CompanyName.ProjectName.Application.Tests/PackageName/CompanyName/ProjectName/TestHostEnvironment.cs b/aspnet-core/templates/aio/content/tests/PackageName.CompanyName.ProjectName.Application.Tests/PackageName/CompanyName/ProjectName/TestHostEnvironment.cs
new file mode 100644
index 000000000..ae140f85d
--- /dev/null
+++ b/aspnet-core/templates/aio/content/tests/PackageName.CompanyName.ProjectName.Application.Tests/PackageName/CompanyName/ProjectName/TestHostEnvironment.cs
@@ -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; }
+}
\ No newline at end of file
diff --git a/aspnet-core/templates/aio/content/tests/PackageName.CompanyName.ProjectName.Application.Tests/PackageName/CompanyName/ProjectName/Users/UserAppServiceTests.cs b/aspnet-core/templates/aio/content/tests/PackageName.CompanyName.ProjectName.Application.Tests/PackageName/CompanyName/ProjectName/Users/UserAppServiceTests.cs
new file mode 100644
index 000000000..212d79fe2
--- /dev/null
+++ b/aspnet-core/templates/aio/content/tests/PackageName.CompanyName.ProjectName.Application.Tests/PackageName/CompanyName/ProjectName/Users/UserAppServiceTests.cs
@@ -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
+{
+ ///
+ /// UserAppService 的单元测试
+ ///
+ [Collection("Database")]
+ public class UserAppServiceTests : ProjectNameApplicationTestBase
+ {
+ private readonly IUserAppService _userAppService;
+ private readonly IUserManager _userManager;
+
+ public UserAppServiceTests()
+ {
+ _userAppService = GetRequiredService();
+ _userManager = GetRequiredService();
+ }
+
+ [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(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(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(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 CreateTestUserAsync(string nickName, string password)
+ {
+ return await WithUnitOfWorkAsync(async () =>
+ {
+ var input = new CreateUpdateUserDto
+ {
+ NickName = nickName,
+ Password = password,
+ IsActive = true
+ };
+
+ return await _userAppService.CreateAsync(input);
+ });
+ }
+ }
+}
\ No newline at end of file
diff --git a/aspnet-core/templates/aio/content/tests/PackageName.CompanyName.ProjectName.EntityFrameworkCore.Tests/PackageName.CompanyName.ProjectName.EntityFrameworkCore.Tests.csproj b/aspnet-core/templates/aio/content/tests/PackageName.CompanyName.ProjectName.EntityFrameworkCore.Tests/PackageName.CompanyName.ProjectName.EntityFrameworkCore.Tests.csproj
index 0a3e9f02c..944bbe75a 100644
--- a/aspnet-core/templates/aio/content/tests/PackageName.CompanyName.ProjectName.EntityFrameworkCore.Tests/PackageName.CompanyName.ProjectName.EntityFrameworkCore.Tests.csproj
+++ b/aspnet-core/templates/aio/content/tests/PackageName.CompanyName.ProjectName.EntityFrameworkCore.Tests/PackageName.CompanyName.ProjectName.EntityFrameworkCore.Tests.csproj
@@ -8,10 +8,14 @@
-
+
+
+
+
+
diff --git a/aspnet-core/templates/aio/content/tests/PackageName.CompanyName.ProjectName.EntityFrameworkCore.Tests/PackageName/CompanyName/ProjectName/EntityFrameworkCore/ProjectNameEntityFrameworkCoreTestModule.cs b/aspnet-core/templates/aio/content/tests/PackageName.CompanyName.ProjectName.EntityFrameworkCore.Tests/PackageName/CompanyName/ProjectName/EntityFrameworkCore/ProjectNameEntityFrameworkCoreTestModule.cs
index da8ce7c6c..b5fff765e 100644
--- a/aspnet-core/templates/aio/content/tests/PackageName.CompanyName.ProjectName.EntityFrameworkCore.Tests/PackageName/CompanyName/ProjectName/EntityFrameworkCore/ProjectNameEntityFrameworkCoreTestModule.cs
+++ b/aspnet-core/templates/aio/content/tests/PackageName.CompanyName.ProjectName.EntityFrameworkCore.Tests/PackageName/CompanyName/ProjectName/EntityFrameworkCore/ProjectNameEntityFrameworkCoreTestModule.cs
@@ -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(options =>
+ {
+ options.ConnectionStrings.Default = connectionString;
+ });
- Configure(options =>
+ Configure(options => { options.Kind = DateTimeKind.Utc; });
+ context.Services.AddAbpDbContext(options =>
{
- options.Configure(abpDbContextConfigurationContext =>
- {
- abpDbContextConfigurationContext.DbContextOptions.EnableDetailedErrors();
- abpDbContextConfigurationContext.DbContextOptions.EnableSensitiveDataLogging();
+ options.AddDefaultRepositories(true);
+ });
- abpDbContextConfigurationContext.DbContextOptions.UseInMemoryDatabase(databaseName);
- });
+ // 配置所有DbContext
+ Configure(options =>
+ {
+ AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true);
+ options.UseNpgsql();
});
Configure(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();
+ // 重置数据库
+ dbContext.Database.EnsureDeleted();
+ // // 创建数据库
+ dbContext.Database.EnsureCreated();
+ dbContext.Database.GenerateCreateScript();
+ // dbContext.Database.Migrate();
+
+ // 初始化种子数据
+ var dataSeeder = context.ServiceProvider.GetRequiredService();
+ AsyncHelper.RunSync(() => dataSeeder.SeedAsync());
+ }
+
+ public override void OnApplicationShutdown(ApplicationShutdownContext context)
+ {
+ }
+}
\ No newline at end of file