using AxiOmron.PcbCheck.Models;
using AxiOmron.PcbCheck.Options;
using AxiOmron.PcbCheck.Services.Implementations;
using AxiOmron.PcbCheck.Services.Interfaces;
namespace AxiOmron.PcbCheck.Tests;
///
/// 验证流程后台服务的 SFTP 启动探活行为。
///
public sealed class WorkflowHostedServiceTests
{
///
/// 启动探活失败时,不应抛出异常,且应写入运行态状态。
///
/// 异步测试任务。
[Fact]
public async Task ProbeSftpOnStartupAsync_ShouldUpdateSnapshot_WhenConnectionFails()
{
var stateStore = new AppStateStore();
var service = new WorkflowHostedService(
new FakePlcService(),
new FakeScannerService(),
new FakeSftpLookupService
{
TestOutcome = new SftpConnectionTestOutcome
{
IsSuccess = false,
IsSystemError = true,
StatusMessage = "启动探活失败"
}
},
new FakeAndonService(),
stateStore,
new AppConfig(),
new FakeAppLogger());
await service.ProbeSftpOnStartupAsync(CancellationToken.None);
Assert.Equal("异常", stateStore.GetSnapshot().SftpStatus);
}
private sealed class FakePlcService : IPlcService
{
public Task ForceReconnectAsync(CancellationToken cancellationToken) => Task.CompletedTask;
public Task ReadSignalsAsync(CancellationToken cancellationToken) => Task.FromResult(new PlcSignalSnapshot());
public Task WriteStateAsync(PlcProcessState state, CancellationToken cancellationToken) => Task.CompletedTask;
}
private sealed class FakeScannerService : IScannerService
{
public Task ForceReconnectAsync(CancellationToken cancellationToken) => Task.CompletedTask;
public Task TestConnectionAsync(CancellationToken cancellationToken) => Task.FromResult(true);
public Task TriggerScanAsync(CancellationToken cancellationToken) => Task.FromResult(new ScanOperationResult());
}
private sealed class FakeSftpLookupService : ISftpLookupService
{
public SftpConnectionTestOutcome TestOutcome { get; set; } = new();
public Task CheckFileAsync(string barcode, CancellationToken cancellationToken) => Task.FromResult(new SftpCheckOutcome());
public Task TestConnectionAsync(SftpOptions? options, CancellationToken cancellationToken)
{
return Task.FromResult(TestOutcome);
}
}
private sealed class FakeAndonService : IAndonService
{
public Task RaiseAlarmAsync(AndonAlarmRequest request, CancellationToken cancellationToken)
=> Task.FromResult(new AndonOperationResult());
public Task TestAsync(CancellationToken cancellationToken)
=> Task.FromResult(new AndonOperationResult());
}
private sealed class FakeAppLogger : IAppLogger
{
public void LogError(string message, bool showInUi = false, params object?[] args) { }
public void LogError(Exception exception, string message, bool showInUi = false, params object?[] args) { }
public void LogInformation(string message, bool showInUi = false, params object?[] args) { }
public void LogWarning(string message, bool showInUi = false, params object?[] args) { }
public void LogWarning(Exception exception, string message, bool showInUi = false, params object?[] args) { }
}
}