- 将AI模型相关端点、命令、处理器移动到模块内部统一管理 - 优化数据库迁移脚本,添加对不同环境表状态的兼容处理逻辑 - 为异常处理添加错误码枚举参数,统一错误处理方式 - 重构多处业务逻辑中的异常抛出方式,增强代码一致性 - 移除独立的组件清单分组和项目定义,简化前端物料面板数据结构 - 修复测试代码中实体引用路径错误问题 - 添加新的监控模块测试项目到解决方案文件中
109 lines
3.8 KiB
C#
109 lines
3.8 KiB
C#
using System.Net;
|
|
using System.Text;
|
|
using BuildFlow.Shared.Domain.Exceptions;
|
|
using FluentAssertions;
|
|
using Microsoft.Extensions.Logging;
|
|
using Monitoring.Domain.Entities.ExternalSystem;
|
|
using Monitoring.Domain.Enums;
|
|
using Monitoring.Domain.Values;
|
|
using Monitoring.Infrastructure.Connectors;
|
|
|
|
namespace BuildFlow.Monitoring.Tests.Connectors;
|
|
|
|
/// <summary>u号租订单同步日志安全测试。</summary>
|
|
public class UHaoZuConnectorLoggingTests
|
|
{
|
|
[Fact]
|
|
public async Task FetchAsync_ShouldNotLogOrderResponseBody()
|
|
{
|
|
const string sensitiveOrderId = "secret-order-123";
|
|
var handler = new SequenceHttpMessageHandler(
|
|
"""{"responseCode":"0000","object":{}}""",
|
|
$$"""{"responseCode":"0000","object":[{"id":"{{sensitiveOrderId}}","createTime":1721300000000}]}""");
|
|
var resolver = new ConnectorCredentialResolver(new StubHttpClientFactory(handler));
|
|
var logger = new CapturingLogger<UHaoZuConnector>();
|
|
var connector = new UHaoZuConnector(resolver, logger);
|
|
var system = new ExternalSystemEntity
|
|
{
|
|
Data = new SystemData
|
|
{
|
|
Name = "u号租",
|
|
SystemType = ExternalSystemTypeEnum.UHaoZu,
|
|
BaseUrl = "https://mapi.uhaozu.com",
|
|
Parameters = new Dictionary<string, string?> { ["maxPages"] = "1" },
|
|
},
|
|
};
|
|
|
|
await connector.FetchAsync(system, default);
|
|
|
|
logger.Messages.Should().NotContain(message => message.Contains(sensitiveOrderId));
|
|
}
|
|
|
|
[Fact]
|
|
public async Task FetchAsync_ShouldFailWhenOrderApiRejectsSession()
|
|
{
|
|
var handler = new SequenceHttpMessageHandler(
|
|
"""{"responseCode":"0000","object":{}}""",
|
|
"""{"responseCode":"9996","responseMsg":"not logged in"}""");
|
|
var resolver = new ConnectorCredentialResolver(new StubHttpClientFactory(handler));
|
|
var connector = new UHaoZuConnector(resolver, new CapturingLogger<UHaoZuConnector>());
|
|
var system = CreateSystem();
|
|
|
|
var action = () => connector.FetchAsync(system, default);
|
|
|
|
await action.Should().ThrowAsync<BusinessException>()
|
|
.WithMessage("*not logged in*");
|
|
}
|
|
|
|
private static ExternalSystemEntity CreateSystem() => new()
|
|
{
|
|
Data = new SystemData
|
|
{
|
|
Name = "u号租",
|
|
SystemType = ExternalSystemTypeEnum.UHaoZu,
|
|
BaseUrl = "https://mapi.uhaozu.com",
|
|
Parameters = new Dictionary<string, string?> { ["maxPages"] = "1" },
|
|
},
|
|
};
|
|
|
|
private sealed class StubHttpClientFactory(HttpMessageHandler handler) : IHttpClientFactory
|
|
{
|
|
public HttpClient CreateClient(string name) => new(handler, disposeHandler: false);
|
|
}
|
|
|
|
private sealed class SequenceHttpMessageHandler(params string[] responses) : HttpMessageHandler
|
|
{
|
|
private readonly Queue<string> _responses = new(responses);
|
|
|
|
protected override Task<HttpResponseMessage> SendAsync(
|
|
HttpRequestMessage request,
|
|
CancellationToken cancellationToken)
|
|
{
|
|
var body = _responses.Dequeue();
|
|
return Task.FromResult(new HttpResponseMessage(HttpStatusCode.OK)
|
|
{
|
|
Content = new StringContent(body, Encoding.UTF8, "application/json"),
|
|
});
|
|
}
|
|
}
|
|
|
|
private sealed class CapturingLogger<T> : ILogger<T>
|
|
{
|
|
public List<string> Messages { get; } = [];
|
|
|
|
public IDisposable? BeginScope<TState>(TState state) where TState : notnull => null;
|
|
|
|
public bool IsEnabled(LogLevel logLevel) => true;
|
|
|
|
public void Log<TState>(
|
|
LogLevel logLevel,
|
|
EventId eventId,
|
|
TState state,
|
|
Exception? exception,
|
|
Func<TState, Exception?, string> formatter)
|
|
{
|
|
Messages.Add(formatter(state, exception));
|
|
}
|
|
}
|
|
}
|