xiangning bdd1ad39bb fix: PlatformInfrastructureModule 补 UseSnakeCaseNamingConvention
根因:PlatformDbContext 注册时缺少 UseSnakeCaseNamingConvention,
导致 EF 查询用 PascalCase 列名("Id")但实际表是 snake_case("id"),
报 column u.Id does not exist。
2026-07-03 11:47:37 +08:00

96 lines
3.8 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

namespace BuildFlow.Architecture.Tests;
using Xunit;
/// <summary>
/// BuildFlow Host 架构约束测试。确保后台只有 BuildFlow Host 一个启动入口,
/// 业务模块(Domain/Application/Infrastructure 三层)不能退化为独立进程。
/// HTTP 层已统一并入 BuildFlow.Host,模块不再保留 Api 类库。
/// </summary>
public class HostArchitectureTests
{
[Fact]
public void BusinessModulesShouldNotContainStandaloneProgramEntryPoints()
{
var repoRoot = FindRepoRoot();
var moduleRoot = Path.Combine(repoRoot.FullName, "src", "modules");
var programFiles = Directory
.EnumerateFiles(moduleRoot, "Program.cs", SearchOption.AllDirectories)
.Where(path => !ContainsPathSegment(path, "bin") && !ContainsPathSegment(path, "obj"))
.Select(path => Path.GetRelativePath(repoRoot.FullName, path).Replace('\\', '/'))
.Order(StringComparer.Ordinal)
.ToArray();
Assert.True(
programFiles.Length == 0,
"业务模块不允许包含独立 Program.cs,后台应只由 src/BuildFlow.Host/Program.cs 统一启动。当前残留:" +
Environment.NewLine +
string.Join(Environment.NewLine, programFiles));
}
[Fact]
public void BusinessModulesShouldNotContainLaunchProfiles()
{
var repoRoot = FindRepoRoot();
var moduleRoot = Path.Combine(repoRoot.FullName, "src", "modules");
var launchProfiles = Directory
.EnumerateFiles(moduleRoot, "launchSettings.json", SearchOption.AllDirectories)
.Where(path => !ContainsPathSegment(path, "bin") && !ContainsPathSegment(path, "obj"))
.Select(path => Path.GetRelativePath(repoRoot.FullName, path).Replace('\\', '/'))
.Order(StringComparer.Ordinal)
.ToArray();
Assert.True(
launchProfiles.Length == 0,
"业务模块不允许保留独立启动配置 launchSettings.json。当前残留:" +
Environment.NewLine +
string.Join(Environment.NewLine, launchProfiles));
}
[Fact]
public void BusinessModulesShouldNotHaveStandaloneApiProjects()
{
var repoRoot = FindRepoRoot();
var moduleRoot = Path.Combine(repoRoot.FullName, "src", "modules");
var apiProjects = Directory
.EnumerateFiles(moduleRoot, "*.Api.csproj", SearchOption.AllDirectories)
.Concat(Directory.EnumerateFiles(moduleRoot, "*Api.csproj", SearchOption.AllDirectories))
.Where(path => !ContainsPathSegment(path, "bin") && !ContainsPathSegment(path, "obj"))
.Distinct(StringComparer.Ordinal)
.Select(path => Path.GetRelativePath(repoRoot.FullName, path).Replace('\\', '/'))
.Order(StringComparer.Ordinal)
.ToArray();
Assert.True(
apiProjects.Length == 0,
"业务模块不允许保留独立 Api 类库项目(HTTP 层已统一并入 BuildFlow.Host)。当前残留:" +
Environment.NewLine +
string.Join(Environment.NewLine, apiProjects));
}
private static DirectoryInfo FindRepoRoot()
{
var current = new DirectoryInfo(AppContext.BaseDirectory);
while (current is not null)
{
if (File.Exists(Path.Combine(current.FullName, "BuildFlow.slnx")))
{
return current;
}
current = current.Parent;
}
throw new InvalidOperationException("无法定位 BuildFlow.slnx,架构测试无法确定仓库边界。");
}
private static bool ContainsPathSegment(string path, string segment)
{
return path.Split(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar)
.Any(part => string.Equals(part, segment, StringComparison.Ordinal));
}
}