using FsCheck; using FsCheck.Xunit; using MiAssessment.Core.Interfaces; using MiAssessment.Core.Services; using MiAssessment.Model.Data; using MiAssessment.Model.Models.Payment; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Moq; using Xunit; namespace MiAssessment.Tests.Services; /// /// 微信支付版本路由属性测试 /// **Feature: wechat-pay-v3-upgrade** /// public class WechatPayVersionRoutingPropertyTests { #region Property 4: 版本路由正确性 /// /// **Feature: wechat-pay-v3-upgrade, Property 4: 版本路由正确性** /// *For any* 支付请求,当商户配置的 PayVersion 为 "V3" 时,应该调用 V3 接口; /// 当 PayVersion 为 "V2" 时,应该调用 V2 接口。 /// **Validates: Requirements 3.1, 3.5** /// [Property(MaxTest = 100)] public bool VersionRouting_ShouldRouteToCorrectService_BasedOnPayVersion( NonEmptyString orderNo, PositiveInt userId, PositiveInt amount, bool isV3) { // Arrange var payVersion = isV3 ? "V3" : "V2"; // 安全地处理订单号,确保不会越界 var cleanOrderNo = orderNo.Get.Replace("-", ""); var orderNoStr = $"MYH{(cleanOrderNo.Length > 10 ? cleanOrderNo.Substring(0, 10) : cleanOrderNo)}"; var merchantConfig = new WechatPayMerchantConfig { Name = "测试商户", MchId = "1738725801", AppId = "wx1234567890", Key = "testkey123456789012345678901234", OrderPrefix = "MYH", PayVersion = payVersion, ApiV3Key = isV3 ? "d1cxc0vXCUH2984901DxddPJMYqcwcnd" : null, CertSerialNo = isV3 ? "SERIAL123456" : null, PrivateKeyPath = isV3 ? "certs/test/key.pem" : null, WechatPublicKeyId = isV3 ? "PUBKEYID123" : null, WechatPublicKeyPath = isV3 ? "certs/test/pub.pem" : null, NotifyUrl = "https://example.com/notify" }; // 验证版本路由逻辑 var shouldUseV3 = merchantConfig.PayVersion == "V3"; // 属性:PayVersion 为 "V3" 时应该路由到 V3,否则路由到 V2 return shouldUseV3 == isV3; } /// /// **Feature: wechat-pay-v3-upgrade, Property 4: 版本路由正确性** /// *For any* 商户配置,PayVersion 只能是 "V2" 或 "V3",默认为 "V2"。 /// **Validates: Requirements 3.1, 3.5** /// [Fact] public void PayVersion_DefaultValue_ShouldBeV2() { var config = new WechatPayMerchantConfig(); Assert.Equal("V2", config.PayVersion); } /// /// **Feature: wechat-pay-v3-upgrade, Property 4: 版本路由正确性** /// *For any* V3 配置,必须包含 V3 必要字段才能正确路由。 /// **Validates: Requirements 3.1** /// [Property(MaxTest = 100)] public bool V3Config_ShouldHaveRequiredFields_WhenPayVersionIsV3( NonEmptyString apiV3Key, NonEmptyString certSerialNo, NonEmptyString privateKeyPath) { var config = new WechatPayMerchantConfig { PayVersion = "V3", ApiV3Key = apiV3Key.Get, CertSerialNo = certSerialNo.Get, PrivateKeyPath = privateKeyPath.Get }; // V3 配置必须有这些字段 var hasRequiredFields = !string.IsNullOrEmpty(config.ApiV3Key) && !string.IsNullOrEmpty(config.CertSerialNo) && !string.IsNullOrEmpty(config.PrivateKeyPath); return config.PayVersion == "V3" && hasRequiredFields; } /// /// **Feature: wechat-pay-v3-upgrade, Property 4: 版本路由正确性** /// *For any* V2 配置,V3 字段可以为空。 /// **Validates: Requirements 3.5** /// [Fact] public void V2Config_ShouldWorkWithoutV3Fields() { var config = new WechatPayMerchantConfig { Name = "V2商户", MchId = "1234567890", AppId = "wx1234567890", Key = "v2key12345678901234567890123456", PayVersion = "V2", // V3 字段为空 ApiV3Key = null, CertSerialNo = null, PrivateKeyPath = null }; // V2 配置不需要 V3 字段 Assert.Equal("V2", config.PayVersion); Assert.Null(config.ApiV3Key); Assert.Null(config.CertSerialNo); Assert.Null(config.PrivateKeyPath); } /// /// **Feature: wechat-pay-v3-upgrade, Property 4: 版本路由正确性** /// 测试版本路由决策逻辑的正确性。 /// **Validates: Requirements 3.1, 3.5** /// [Theory] [InlineData("V3", true)] [InlineData("V2", false)] [InlineData("v3", false)] // 大小写敏感 [InlineData("v2", false)] // 大小写敏感 [InlineData("", false)] [InlineData(null, false)] public void VersionRouting_Decision_ShouldBeCorrect(string? payVersion, bool expectedV3Route) { // 版本路由决策逻辑 var shouldRouteToV3 = payVersion == "V3"; Assert.Equal(expectedV3Route, shouldRouteToV3); } /// /// **Feature: wechat-pay-v3-upgrade, Property 4: 版本路由正确性** /// *For any* 订单号前缀,版本路由应该基于商户配置而非订单号。 /// **Validates: Requirements 3.1, 3.5** /// [Property(MaxTest = 100)] public bool VersionRouting_ShouldBeBasedOnMerchantConfig_NotOrderNo( NonEmptyString orderPrefix, bool isV3) { // 安全地处理订单前缀 var prefix = orderPrefix.Get.Length >= 3 ? orderPrefix.Get.Substring(0, 3) : orderPrefix.Get.PadRight(3, 'X'); // 创建两个商户配置,一个 V2,一个 V3 var v2Config = new WechatPayMerchantConfig { OrderPrefix = prefix, PayVersion = "V2" }; var v3Config = new WechatPayMerchantConfig { OrderPrefix = prefix, PayVersion = "V3" }; // 相同的订单前缀,不同的版本配置 // 版本路由应该基于 PayVersion 字段 var v2ShouldRouteToV3 = v2Config.PayVersion == "V3"; var v3ShouldRouteToV3 = v3Config.PayVersion == "V3"; return !v2ShouldRouteToV3 && v3ShouldRouteToV3; } #endregion }