✨ feat(*): 重构PCB放行流程并接入双扫码校验
- 将流程改为 OMRON FINS + TCP 双扫码 + SFTP 文件校验 - 新增文件校验与扫码结果汇总实现,补充对应单测 - 同步更新流程设计文档、配置和系统设置页面文案
This commit is contained in:
183
tests/AxiOmron.PcbCheck.Tests/LocalFileCheckProviderTests.cs
Normal file
183
tests/AxiOmron.PcbCheck.Tests/LocalFileCheckProviderTests.cs
Normal file
@@ -0,0 +1,183 @@
|
||||
using AxiOmron.PcbCheck.Models;
|
||||
using AxiOmron.PcbCheck.Options;
|
||||
using AxiOmron.PcbCheck.Services.Implementations;
|
||||
using AxiOmron.PcbCheck.Services.Interfaces;
|
||||
using Xunit;
|
||||
|
||||
namespace AxiOmron.PcbCheck.Tests;
|
||||
|
||||
/// <summary>
|
||||
/// 验证本地磁盘文件校验提供程序的目录检查与文件匹配行为。
|
||||
/// </summary>
|
||||
public sealed class LocalFileCheckProviderTests : IDisposable
|
||||
{
|
||||
private readonly string _rootPath;
|
||||
|
||||
/// <summary>
|
||||
/// 初始化临时测试目录。
|
||||
/// </summary>
|
||||
public LocalFileCheckProviderTests()
|
||||
{
|
||||
_rootPath = Path.Combine(Path.GetTempPath(), "AxiOmronLocalFileCheckTests", Guid.NewGuid().ToString("N"));
|
||||
Directory.CreateDirectory(_rootPath);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 清理临时测试目录。
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
if (Directory.Exists(_rootPath))
|
||||
{
|
||||
Directory.Delete(_rootPath, recursive: true);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 本地根目录为空时,应返回配置异常。
|
||||
/// </summary>
|
||||
/// <returns>异步测试任务。</returns>
|
||||
[Fact]
|
||||
public async Task TestConnectionAsync_ShouldReturnConfigurationError_WhenRootPathIsEmpty()
|
||||
{
|
||||
var provider = CreateProvider();
|
||||
var config = new AppConfig
|
||||
{
|
||||
FileCheck = new FileCheckOptions
|
||||
{
|
||||
Local = new LocalFileCheckOptions { RootPath = string.Empty }
|
||||
}
|
||||
};
|
||||
|
||||
FileCheckTestOutcome outcome = await provider.TestConnectionAsync(config, CancellationToken.None);
|
||||
|
||||
Assert.True(outcome.IsConfigurationError);
|
||||
Assert.Contains("本地文件校验目录未配置", outcome.StatusMessage);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 本地根目录不存在时,应返回配置异常。
|
||||
/// </summary>
|
||||
/// <returns>异步测试任务。</returns>
|
||||
[Fact]
|
||||
public async Task TestConnectionAsync_ShouldReturnConfigurationError_WhenRootPathDoesNotExist()
|
||||
{
|
||||
var provider = CreateProvider();
|
||||
var config = CreateConfig(Path.Combine(_rootPath, "missing"));
|
||||
|
||||
FileCheckTestOutcome outcome = await provider.TestConnectionAsync(config, CancellationToken.None);
|
||||
|
||||
Assert.True(outcome.IsConfigurationError);
|
||||
Assert.Contains("本地文件校验目录不存在", outcome.StatusMessage);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 文件名精确匹配模板时,应返回命中文件路径。
|
||||
/// </summary>
|
||||
/// <returns>异步测试任务。</returns>
|
||||
[Fact]
|
||||
public async Task CheckFileAsync_ShouldMatchExactFileName()
|
||||
{
|
||||
string filePath = Path.Combine(_rootPath, "PCB-001.txt");
|
||||
await File.WriteAllTextAsync(filePath, "ok");
|
||||
var provider = CreateProvider();
|
||||
|
||||
FileCheckOutcome outcome = await provider.CheckFileAsync("PCB-001", CreateConfig(_rootPath), CancellationToken.None);
|
||||
|
||||
Assert.True(outcome.Exists);
|
||||
Assert.Equal(filePath, outcome.MatchedFilePath);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 文件名包含条码时,应返回命中文件路径。
|
||||
/// </summary>
|
||||
/// <returns>异步测试任务。</returns>
|
||||
[Fact]
|
||||
public async Task CheckFileAsync_ShouldMatchFileNameContainingBarcode()
|
||||
{
|
||||
string filePath = Path.Combine(_rootPath, "prefix-PCB-002-result.dat");
|
||||
await File.WriteAllTextAsync(filePath, "ok");
|
||||
var provider = CreateProvider();
|
||||
|
||||
FileCheckOutcome outcome = await provider.CheckFileAsync("PCB-002", CreateConfig(_rootPath), CancellationToken.None);
|
||||
|
||||
Assert.True(outcome.Exists);
|
||||
Assert.Equal(filePath, outcome.MatchedFilePath);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 文件名模板包含通配符时,应按通配符匹配。
|
||||
/// </summary>
|
||||
/// <returns>异步测试任务。</returns>
|
||||
[Fact]
|
||||
public async Task CheckFileAsync_ShouldMatchWildcardPattern()
|
||||
{
|
||||
string filePath = Path.Combine(_rootPath, "PCB-003_result.txt");
|
||||
await File.WriteAllTextAsync(filePath, "ok");
|
||||
var provider = CreateProvider();
|
||||
AppConfig config = CreateConfig(_rootPath);
|
||||
config.FileCheck.FileNamePattern = "${barcode}_*.txt";
|
||||
|
||||
FileCheckOutcome outcome = await provider.CheckFileAsync("PCB-003", config, CancellationToken.None);
|
||||
|
||||
Assert.True(outcome.Exists);
|
||||
Assert.Equal(filePath, outcome.MatchedFilePath);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建本地文件校验提供程序。
|
||||
/// </summary>
|
||||
/// <returns>本地文件校验提供程序。</returns>
|
||||
private static LocalFileCheckProvider CreateProvider()
|
||||
{
|
||||
return new LocalFileCheckProvider(new FakeAppLogger<LocalFileCheckProvider>());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建本地文件校验测试配置。
|
||||
/// </summary>
|
||||
/// <param name="rootPath">本地根目录。</param>
|
||||
/// <returns>测试配置。</returns>
|
||||
private static AppConfig CreateConfig(string rootPath)
|
||||
{
|
||||
return new AppConfig
|
||||
{
|
||||
FileCheck = new FileCheckOptions
|
||||
{
|
||||
Provider = FileCheckProvider.Local,
|
||||
FileNamePattern = "${barcode}.txt",
|
||||
Local = new LocalFileCheckOptions
|
||||
{
|
||||
RootPath = rootPath
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 提供本地文件校验测试用的空日志实现。
|
||||
/// </summary>
|
||||
/// <typeparam name="TCategoryName">日志分类类型。</typeparam>
|
||||
private sealed class FakeAppLogger<TCategoryName> : IAppLogger<TCategoryName>
|
||||
{
|
||||
public void LogError(string message, bool showInUi = true, params object?[] args)
|
||||
{
|
||||
}
|
||||
|
||||
public void LogError(Exception exception, string message, bool showInUi = true, params object?[] args)
|
||||
{
|
||||
}
|
||||
|
||||
public void LogInformation(string message, bool showInUi = true, params object?[] args)
|
||||
{
|
||||
}
|
||||
|
||||
public void LogWarning(string message, bool showInUi = true, params object?[] args)
|
||||
{
|
||||
}
|
||||
|
||||
public void LogWarning(Exception exception, string message, bool showInUi = true, params object?[] args)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user