1486 lines
45 KiB
C#
1486 lines
45 KiB
C#
using System.Text.Json;
|
||
using System.Text.Json.Serialization;
|
||
using HoneyBox.Model.Base;
|
||
using HoneyBox.Model.Models;
|
||
using HoneyBox.Model.Models.Order;
|
||
using HoneyBox.Model.Models.Goods;
|
||
using HoneyBox.Model.Models.Payment;
|
||
using HoneyBox.Model.Models.Lottery;
|
||
using Xunit;
|
||
|
||
namespace HoneyBox.Tests.Integration;
|
||
|
||
/// <summary>
|
||
/// API响应格式验证测试
|
||
/// 验证所有接口响应格式与PHP API一致
|
||
/// Requirements: 18.1-18.4
|
||
/// </summary>
|
||
public class ApiResponseFormatTests
|
||
{
|
||
private readonly JsonSerializerOptions _jsonOptions;
|
||
|
||
public ApiResponseFormatTests()
|
||
{
|
||
_jsonOptions = new JsonSerializerOptions
|
||
{
|
||
PropertyNamingPolicy = null, // Use JsonPropertyName attributes
|
||
WriteIndented = false
|
||
};
|
||
}
|
||
|
||
#region ApiResponse Base Format Tests
|
||
|
||
/// <summary>
|
||
/// 验证ApiResponse基类使用正确的snake_case字段名
|
||
/// Requirements: 18.1, 18.3
|
||
/// </summary>
|
||
[Fact]
|
||
public void ApiResponse_ShouldUseCorrectFieldNames()
|
||
{
|
||
// Arrange
|
||
var response = ApiResponse.Success("success");
|
||
|
||
// Act
|
||
var json = JsonSerializer.Serialize(response, _jsonOptions);
|
||
|
||
// Assert
|
||
Assert.Contains("\"status\":", json);
|
||
Assert.Contains("\"msg\":", json);
|
||
Assert.DoesNotContain("\"Status\":", json);
|
||
Assert.DoesNotContain("\"Msg\":", json);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 验证ApiResponse<T>包含data字段
|
||
/// Requirements: 18.1, 18.3
|
||
/// </summary>
|
||
[Fact]
|
||
public void ApiResponseGeneric_ShouldIncludeDataField()
|
||
{
|
||
// Arrange
|
||
var response = ApiResponse<string>.Success("test data");
|
||
|
||
// Act
|
||
var json = JsonSerializer.Serialize(response, _jsonOptions);
|
||
|
||
// Assert
|
||
Assert.Contains("\"status\":", json);
|
||
Assert.Contains("\"msg\":", json);
|
||
Assert.Contains("\"data\":", json);
|
||
Assert.DoesNotContain("\"Data\":", json);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 验证成功响应status=1
|
||
/// Requirements: 18.1
|
||
/// </summary>
|
||
[Fact]
|
||
public void ApiResponse_Success_ShouldHaveStatus1()
|
||
{
|
||
// Arrange & Act
|
||
var response = ApiResponse.Success();
|
||
|
||
// Assert
|
||
Assert.Equal(1, response.Status);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 验证失败响应status=0
|
||
/// Requirements: 18.1
|
||
/// </summary>
|
||
[Fact]
|
||
public void ApiResponse_Fail_ShouldHaveStatus0()
|
||
{
|
||
// Arrange & Act
|
||
var response = ApiResponse.Fail("error");
|
||
|
||
// Assert
|
||
Assert.Equal(0, response.Status);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 验证未授权响应status=-1
|
||
/// Requirements: 18.1
|
||
/// </summary>
|
||
[Fact]
|
||
public void ApiResponse_Unauthorized_ShouldHaveStatusMinus1()
|
||
{
|
||
// Arrange & Act
|
||
var response = ApiResponse.Unauthorized();
|
||
|
||
// Assert
|
||
Assert.Equal(-1, response.Status);
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region Order Models Format Tests
|
||
|
||
/// <summary>
|
||
/// 验证OrderMoneyRequest使用snake_case
|
||
/// Requirements: 18.2
|
||
/// </summary>
|
||
[Fact]
|
||
public void OrderMoneyRequest_ShouldUseSnakeCase()
|
||
{
|
||
// Arrange
|
||
var request = new OrderMoneyRequest
|
||
{
|
||
GoodsId = 1,
|
||
Num = 1,
|
||
PrizeNum = 1,
|
||
UseMoneyIs = 1,
|
||
UseIntegralIs = 1,
|
||
UseMoney2Is = 1
|
||
};
|
||
|
||
// Act
|
||
var json = JsonSerializer.Serialize(request, _jsonOptions);
|
||
|
||
// Assert
|
||
Assert.Contains("\"goods_id\":", json);
|
||
Assert.Contains("\"num\":", json);
|
||
Assert.Contains("\"prize_num\":", json);
|
||
Assert.Contains("\"use_money_is\":", json);
|
||
Assert.Contains("\"use_integral_is\":", json);
|
||
Assert.Contains("\"use_money2_is\":", json);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 验证OrderCalculationDto使用snake_case
|
||
/// Requirements: 18.2
|
||
/// </summary>
|
||
[Fact]
|
||
public void OrderCalculationDto_ShouldUseSnakeCase()
|
||
{
|
||
// Arrange
|
||
var dto = new OrderCalculationDto
|
||
{
|
||
OrderTotal = "100.00",
|
||
Price = "10.00",
|
||
Money = "50.00",
|
||
Integral = "100.00",
|
||
Score = 20.00m,
|
||
UseMoney = "10.00",
|
||
UseIntegral = "5.00",
|
||
UseMoney2 = 3.00m,
|
||
CouponPrice = "2.00"
|
||
};
|
||
|
||
// Act
|
||
var json = JsonSerializer.Serialize(dto, _jsonOptions);
|
||
|
||
// Assert
|
||
Assert.Contains("\"order_total\":", json);
|
||
Assert.Contains("\"price\":", json);
|
||
Assert.Contains("\"money\":", json);
|
||
Assert.Contains("\"integral\":", json);
|
||
Assert.Contains("\"score\":", json);
|
||
Assert.Contains("\"use_money\":", json);
|
||
Assert.Contains("\"use_integral\":", json);
|
||
Assert.Contains("\"coupon_price\":", json);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 验证OrderBuyResponseDto使用snake_case
|
||
/// Requirements: 18.2
|
||
/// </summary>
|
||
[Fact]
|
||
public void OrderBuyResponseDto_ShouldUseSnakeCase()
|
||
{
|
||
// Arrange
|
||
var dto = new OrderBuyResponseDto
|
||
{
|
||
Status = 1,
|
||
OrderNum = "TEST001"
|
||
};
|
||
|
||
// Act
|
||
var json = JsonSerializer.Serialize(dto, _jsonOptions);
|
||
|
||
// Assert
|
||
Assert.Contains("\"status\":", json);
|
||
Assert.Contains("\"order_num\":", json);
|
||
Assert.Contains("\"res\":", json);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 验证OrderListDto使用snake_case
|
||
/// Requirements: 18.2
|
||
/// </summary>
|
||
[Fact]
|
||
public void OrderListDto_ShouldUseSnakeCase()
|
||
{
|
||
// Arrange
|
||
var dto = new OrderListDto
|
||
{
|
||
Id = 1,
|
||
OrderNum = "TEST001",
|
||
GoodsTitle = "Test",
|
||
GoodsImgUrl = "http://test.com/img.jpg",
|
||
OrderTotal = "100.00",
|
||
Price = "100.00",
|
||
PrizeNum = 1,
|
||
Status = 1,
|
||
AddTime = 1234567890,
|
||
PayTime = 1234567890,
|
||
OrderType = 1
|
||
};
|
||
|
||
// Act
|
||
var json = JsonSerializer.Serialize(dto, _jsonOptions);
|
||
|
||
// Assert
|
||
Assert.Contains("\"id\":", json);
|
||
Assert.Contains("\"order_num\":", json);
|
||
Assert.Contains("\"goods_title\":", json);
|
||
Assert.Contains("\"goods_imgurl\":", json);
|
||
Assert.Contains("\"order_total\":", json);
|
||
Assert.Contains("\"price\":", json);
|
||
Assert.Contains("\"prize_num\":", json);
|
||
Assert.Contains("\"status\":", json);
|
||
Assert.Contains("\"addtime\":", json);
|
||
Assert.Contains("\"pay_time\":", json);
|
||
Assert.Contains("\"order_type\":", json);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 验证PrizeOrderLogDto使用snake_case
|
||
/// Requirements: 18.2
|
||
/// </summary>
|
||
[Fact]
|
||
public void PrizeOrderLogDto_ShouldUseSnakeCase()
|
||
{
|
||
// Arrange
|
||
var dto = new PrizeOrderLogDto
|
||
{
|
||
Id = 1,
|
||
UserId = 1,
|
||
GoodsListTitle = "Test",
|
||
GoodsListImgUrl = "http://test.com/img.jpg",
|
||
GoodsListPrice = "100.00",
|
||
GoodsListMoney = "50.00",
|
||
Status = 0,
|
||
LuckNo = 1,
|
||
ShangId = 1
|
||
};
|
||
|
||
// Act
|
||
var json = JsonSerializer.Serialize(dto, _jsonOptions);
|
||
|
||
// Assert
|
||
Assert.Contains("\"id\":", json);
|
||
Assert.Contains("\"user_id\":", json);
|
||
Assert.Contains("\"goodslist_title\":", json);
|
||
Assert.Contains("\"goodslist_imgurl\":", json);
|
||
Assert.Contains("\"goodslist_price\":", json);
|
||
Assert.Contains("\"goodslist_money\":", json);
|
||
Assert.Contains("\"status\":", json);
|
||
Assert.Contains("\"luck_no\":", json);
|
||
Assert.Contains("\"shang_id\":", json);
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region Warehouse Models Format Tests
|
||
|
||
/// <summary>
|
||
/// 验证WarehouseIndexRequest使用snake_case
|
||
/// Requirements: 18.4
|
||
/// </summary>
|
||
[Fact]
|
||
public void WarehouseIndexRequest_ShouldUseSnakeCase()
|
||
{
|
||
// Arrange
|
||
var request = new WarehouseIndexRequest
|
||
{
|
||
Page = 1,
|
||
PageSize = 10,
|
||
Type = 1
|
||
};
|
||
|
||
// Act
|
||
var json = JsonSerializer.Serialize(request, _jsonOptions);
|
||
|
||
// Assert
|
||
Assert.Contains("\"page\":", json);
|
||
Assert.Contains("\"page_size\":", json);
|
||
Assert.Contains("\"type\":", json);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 验证WarehouseItemDto使用snake_case
|
||
/// Requirements: 18.4
|
||
/// </summary>
|
||
[Fact]
|
||
public void WarehouseItemDto_ShouldUseSnakeCase()
|
||
{
|
||
// Arrange
|
||
var dto = new WarehouseItemDto
|
||
{
|
||
Id = 1,
|
||
GoodsListTitle = "Test",
|
||
GoodsListImgUrl = "http://test.com/img.jpg",
|
||
GoodsListPrice = "100.00",
|
||
GoodsListMoney = "50.00",
|
||
Status = 0,
|
||
AddTime = 1234567890,
|
||
ShangId = 1,
|
||
GoodsId = 1
|
||
};
|
||
|
||
// Act
|
||
var json = JsonSerializer.Serialize(dto, _jsonOptions);
|
||
|
||
// Assert
|
||
Assert.Contains("\"id\":", json);
|
||
Assert.Contains("\"goodslist_title\":", json);
|
||
Assert.Contains("\"goodslist_imgurl\":", json);
|
||
Assert.Contains("\"goodslist_price\":", json);
|
||
Assert.Contains("\"goodslist_money\":", json);
|
||
Assert.Contains("\"status\":", json);
|
||
Assert.Contains("\"addtime\":", json);
|
||
Assert.Contains("\"shang_id\":", json);
|
||
Assert.Contains("\"goods_id\":", json);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 验证RecoveryResultDto使用snake_case
|
||
/// Requirements: 18.4
|
||
/// </summary>
|
||
[Fact]
|
||
public void RecoveryResultDto_ShouldUseSnakeCase()
|
||
{
|
||
// Arrange
|
||
var dto = new RecoveryResultDto
|
||
{
|
||
TotalMoney = "100.00",
|
||
Count = 5,
|
||
RecoveryNum = "REC001",
|
||
UserMoney = "150.00"
|
||
};
|
||
|
||
// Act
|
||
var json = JsonSerializer.Serialize(dto, _jsonOptions);
|
||
|
||
// Assert
|
||
Assert.Contains("\"total_money\":", json);
|
||
Assert.Contains("\"count\":", json);
|
||
Assert.Contains("\"recovery_num\":", json);
|
||
Assert.Contains("\"user_money\":", json);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 验证SendRecordDto使用snake_case
|
||
/// Requirements: 18.4
|
||
/// </summary>
|
||
[Fact]
|
||
public void SendRecordDto_ShouldUseSnakeCase()
|
||
{
|
||
// Arrange
|
||
var dto = new SendRecordDto
|
||
{
|
||
Id = 1,
|
||
SendNum = "SEND001",
|
||
Name = "Test",
|
||
Mobile = "138****0000",
|
||
Address = "Test Address",
|
||
Status = 1,
|
||
StatusName = "待发货",
|
||
Count = 3,
|
||
Freight = "10.00",
|
||
AddTime = "2024-01-01 12:00:00"
|
||
};
|
||
|
||
// Act
|
||
var json = JsonSerializer.Serialize(dto, _jsonOptions);
|
||
|
||
// Assert
|
||
Assert.Contains("\"id\":", json);
|
||
Assert.Contains("\"send_num\":", json);
|
||
Assert.Contains("\"name\":", json);
|
||
Assert.Contains("\"mobile\":", json);
|
||
Assert.Contains("\"address\":", json);
|
||
Assert.Contains("\"status\":", json);
|
||
Assert.Contains("\"status_name\":", json);
|
||
Assert.Contains("\"count\":", json);
|
||
Assert.Contains("\"freight\":", json);
|
||
Assert.Contains("\"addtime\":", json);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 验证LogisticsDto使用snake_case
|
||
/// Requirements: 18.4
|
||
/// </summary>
|
||
[Fact]
|
||
public void LogisticsDto_ShouldUseSnakeCase()
|
||
{
|
||
// Arrange
|
||
var dto = new LogisticsDto
|
||
{
|
||
CourierNumber = "SF123456",
|
||
CourierName = "顺丰速运",
|
||
CourierCode = "SF",
|
||
Count = 3,
|
||
SendNum = "SEND001",
|
||
DeliveryStatus = "已签收"
|
||
};
|
||
|
||
// Act
|
||
var json = JsonSerializer.Serialize(dto, _jsonOptions);
|
||
|
||
// Assert
|
||
Assert.Contains("\"courier_number\":", json);
|
||
Assert.Contains("\"courier_name\":", json);
|
||
Assert.Contains("\"courier_code\":", json);
|
||
Assert.Contains("\"count\":", json);
|
||
Assert.Contains("\"send_num\":", json);
|
||
Assert.Contains("\"delivery_status\":", json);
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region PageResponse Format Tests
|
||
|
||
/// <summary>
|
||
/// 验证PageResponse使用snake_case
|
||
/// Requirements: 18.2, 18.4
|
||
/// </summary>
|
||
[Fact]
|
||
public void PageResponse_ShouldUseSnakeCase()
|
||
{
|
||
// Arrange
|
||
var response = new PageResponse<OrderListDto>
|
||
{
|
||
Data = new List<OrderListDto>(),
|
||
LastPage = 10,
|
||
Total = 100,
|
||
Page = 1,
|
||
PageSize = 10
|
||
};
|
||
|
||
// Act
|
||
var json = JsonSerializer.Serialize(response, _jsonOptions);
|
||
|
||
// Assert
|
||
Assert.Contains("\"data\":", json);
|
||
Assert.Contains("\"last_page\":", json);
|
||
Assert.Contains("\"total\":", json);
|
||
Assert.Contains("\"page\":", json);
|
||
Assert.Contains("\"page_size\":", json);
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region WechatPayParams Format Tests
|
||
|
||
/// <summary>
|
||
/// 验证WechatPayParamsDto使用正确的字段名(微信API要求的camelCase)
|
||
/// Requirements: 18.2
|
||
/// </summary>
|
||
[Fact]
|
||
public void WechatPayParamsDto_ShouldUseCamelCaseForWechatApi()
|
||
{
|
||
// Arrange
|
||
var dto = new WechatPayParamsDto
|
||
{
|
||
AppId = "wx123456",
|
||
TimeStamp = "1234567890",
|
||
NonceStr = "abc123",
|
||
Package = "prepay_id=xxx",
|
||
SignType = "RSA",
|
||
PaySign = "sign123"
|
||
};
|
||
|
||
// Act
|
||
var json = JsonSerializer.Serialize(dto, _jsonOptions);
|
||
|
||
// Assert - 微信支付参数使用camelCase是正确的
|
||
Assert.Contains("\"appId\":", json);
|
||
Assert.Contains("\"timeStamp\":", json);
|
||
Assert.Contains("\"nonceStr\":", json);
|
||
Assert.Contains("\"package\":", json);
|
||
Assert.Contains("\"signType\":", json);
|
||
Assert.Contains("\"paySign\":", json);
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region Complete Response Serialization Tests
|
||
|
||
/// <summary>
|
||
/// 验证完整的订单金额计算响应格式
|
||
/// Requirements: 18.1, 18.2
|
||
/// </summary>
|
||
[Fact]
|
||
public void CompleteOrderCalculationResponse_ShouldMatchPhpFormat()
|
||
{
|
||
// Arrange
|
||
var data = new OrderCalculationDto
|
||
{
|
||
OrderTotal = "100.00",
|
||
Price = "10.00",
|
||
Goods = new GoodsInfoDto { Id = 1, Title = "Test" },
|
||
Money = "50.00",
|
||
Integral = "100.00",
|
||
Score = 20.00m
|
||
};
|
||
var response = ApiResponse<OrderCalculationDto>.Success(data);
|
||
|
||
// Act
|
||
var json = JsonSerializer.Serialize(response, _jsonOptions);
|
||
|
||
// Assert - 验证顶层结构
|
||
Assert.Contains("\"status\":1", json);
|
||
Assert.Contains("\"msg\":\"success\"", json);
|
||
Assert.Contains("\"data\":", json);
|
||
|
||
// Assert - 验证数据字段
|
||
Assert.Contains("\"order_total\":\"100.00\"", json);
|
||
Assert.Contains("\"price\":\"10.00\"", json);
|
||
Assert.Contains("\"goods\":", json);
|
||
Assert.Contains("\"money\":\"50.00\"", json);
|
||
Assert.Contains("\"integral\":\"100.00\"", json);
|
||
Assert.Contains("\"score\":20", json);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 验证完整的仓库首页响应格式
|
||
/// Requirements: 18.3, 18.4
|
||
/// </summary>
|
||
[Fact]
|
||
public void CompleteWarehouseIndexResponse_ShouldMatchPhpFormat()
|
||
{
|
||
// Arrange
|
||
var data = new WarehouseIndexResponseDto
|
||
{
|
||
Total = 100,
|
||
Data = new List<WarehouseGoodsGroupDto>
|
||
{
|
||
new WarehouseGoodsGroupDto
|
||
{
|
||
GoodsId = 1,
|
||
GoodsTitle = "Test",
|
||
OrderList = new List<WarehouseItemDto>
|
||
{
|
||
new WarehouseItemDto
|
||
{
|
||
Id = 1,
|
||
GoodsListTitle = "Prize",
|
||
GoodsListImgUrl = "http://test.com/img.jpg",
|
||
GoodsListPrice = "100.00",
|
||
GoodsListMoney = "50.00",
|
||
Status = 0
|
||
}
|
||
}
|
||
}
|
||
},
|
||
LastPage = 10
|
||
};
|
||
var response = ApiResponse<WarehouseIndexResponseDto>.Success(data);
|
||
|
||
// Act
|
||
var json = JsonSerializer.Serialize(response, _jsonOptions);
|
||
|
||
// Assert - 验证顶层结构
|
||
Assert.Contains("\"status\":1", json);
|
||
Assert.Contains("\"msg\":\"success\"", json);
|
||
Assert.Contains("\"data\":", json);
|
||
|
||
// Assert - 验证数据字段
|
||
Assert.Contains("\"total\":", json);
|
||
Assert.Contains("\"last_page\":", json);
|
||
Assert.Contains("\"goods_id\":", json);
|
||
Assert.Contains("\"goods_title\":", json);
|
||
Assert.Contains("\"goodslist_title\":", json);
|
||
Assert.Contains("\"goodslist_imgurl\":", json);
|
||
Assert.Contains("\"goodslist_price\":", json);
|
||
Assert.Contains("\"goodslist_money\":", json);
|
||
}
|
||
|
||
#endregion
|
||
|
||
|
||
#region Payment System Response Format Tests - Requirements 10.1-10.4
|
||
|
||
/// <summary>
|
||
/// 验证WechatPayResult使用正确的字段名
|
||
/// Requirements: 10.1, 10.3
|
||
/// </summary>
|
||
[Fact]
|
||
public void WechatPayResult_ShouldUseCorrectFieldNames()
|
||
{
|
||
// Arrange
|
||
var result = new WechatPayResult
|
||
{
|
||
Status = 1,
|
||
Msg = "success",
|
||
Data = new WechatPayData
|
||
{
|
||
AppId = "wx123456",
|
||
TimeStamp = "1234567890",
|
||
NonceStr = "abc123",
|
||
Package = "prepay_id=xxx",
|
||
SignType = "MD5",
|
||
PaySign = "sign123",
|
||
IsWeixin = 1
|
||
}
|
||
};
|
||
|
||
// Act
|
||
var json = JsonSerializer.Serialize(result, _jsonOptions);
|
||
|
||
// Assert - 验证顶层结构使用snake_case
|
||
Assert.Contains("\"status\":", json);
|
||
Assert.Contains("\"msg\":", json);
|
||
Assert.Contains("\"data\":", json);
|
||
Assert.DoesNotContain("\"Status\":", json);
|
||
Assert.DoesNotContain("\"Msg\":", json);
|
||
Assert.DoesNotContain("\"Data\":", json);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 验证WechatPayData使用正确的字段名(微信API要求的camelCase)
|
||
/// Requirements: 10.2, 10.4
|
||
/// </summary>
|
||
[Fact]
|
||
public void WechatPayData_ShouldUseCamelCaseForWechatApi()
|
||
{
|
||
// Arrange
|
||
var data = new WechatPayData
|
||
{
|
||
AppId = "wx123456",
|
||
TimeStamp = "1234567890",
|
||
NonceStr = "abc123",
|
||
Package = "prepay_id=xxx",
|
||
SignType = "MD5",
|
||
PaySign = "sign123",
|
||
IsWeixin = 1
|
||
};
|
||
|
||
// Act
|
||
var json = JsonSerializer.Serialize(data, _jsonOptions);
|
||
|
||
// Assert - 微信支付参数使用camelCase(与PHP API一致)
|
||
Assert.Contains("\"appId\":", json);
|
||
Assert.Contains("\"timeStamp\":", json);
|
||
Assert.Contains("\"nonceStr\":", json);
|
||
Assert.Contains("\"package\":", json);
|
||
Assert.Contains("\"signType\":", json);
|
||
Assert.Contains("\"paySign\":", json);
|
||
Assert.Contains("\"is_weixin\":", json); // is_weixin使用snake_case
|
||
}
|
||
|
||
/// <summary>
|
||
/// 验证WechatPayResult成功响应status=1
|
||
/// Requirements: 10.3
|
||
/// </summary>
|
||
[Fact]
|
||
public void WechatPayResult_Success_ShouldHaveStatus1()
|
||
{
|
||
// Arrange
|
||
var result = new WechatPayResult
|
||
{
|
||
Status = 1,
|
||
Msg = "success",
|
||
Data = new WechatPayData()
|
||
};
|
||
|
||
// Assert
|
||
Assert.Equal(1, result.Status);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 验证WechatPayResult失败响应status=0
|
||
/// Requirements: 10.3
|
||
/// </summary>
|
||
[Fact]
|
||
public void WechatPayResult_Fail_ShouldHaveStatus0()
|
||
{
|
||
// Arrange
|
||
var result = new WechatPayResult
|
||
{
|
||
Status = 0,
|
||
Msg = "支付失败"
|
||
};
|
||
|
||
// Assert
|
||
Assert.Equal(0, result.Status);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 验证WechatPayRequest使用snake_case
|
||
/// Requirements: 10.2
|
||
/// </summary>
|
||
[Fact]
|
||
public void WechatPayRequest_ShouldUseSnakeCase()
|
||
{
|
||
// Arrange
|
||
var request = new WechatPayRequest
|
||
{
|
||
OrderNo = "TEST001",
|
||
Amount = 100.00m,
|
||
Body = "商品购买",
|
||
Attach = "order_yfs",
|
||
OpenId = "openid123",
|
||
UserId = 1
|
||
};
|
||
|
||
// Act
|
||
var json = JsonSerializer.Serialize(request, _jsonOptions);
|
||
|
||
// Assert
|
||
Assert.Contains("\"order_no\":", json);
|
||
Assert.Contains("\"amount\":", json);
|
||
Assert.Contains("\"body\":", json);
|
||
Assert.Contains("\"attach\":", json);
|
||
Assert.Contains("\"open_id\":", json);
|
||
Assert.Contains("\"user_id\":", json);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 验证PaymentRecordDto使用snake_case
|
||
/// Requirements: 10.2
|
||
/// </summary>
|
||
[Fact]
|
||
public void PaymentRecordDto_ShouldUseSnakeCase()
|
||
{
|
||
// Arrange
|
||
var dto = new HoneyBox.Model.Models.Payment.PaymentRecordDto
|
||
{
|
||
Id = 1,
|
||
UserId = 1,
|
||
OrderNum = "TEST001",
|
||
ChangeMoney = "100.00",
|
||
Content = "支付测试",
|
||
PayType = 1,
|
||
PayTypeText = "微信支付",
|
||
CreatedAt = 1234567890
|
||
};
|
||
|
||
// Act
|
||
var json = JsonSerializer.Serialize(dto, _jsonOptions);
|
||
|
||
// Assert
|
||
Assert.Contains("\"id\":", json);
|
||
Assert.Contains("\"user_id\":", json);
|
||
Assert.Contains("\"order_num\":", json);
|
||
Assert.Contains("\"change_money\":", json);
|
||
Assert.Contains("\"content\":", json);
|
||
Assert.Contains("\"pay_type\":", json);
|
||
Assert.Contains("\"pay_type_text\":", json);
|
||
Assert.Contains("\"created_at\":", json);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 验证完整的微信支付响应格式与PHP API一致
|
||
/// Requirements: 10.1-10.4
|
||
/// </summary>
|
||
[Fact]
|
||
public void CompleteWechatPayResponse_ShouldMatchPhpFormat()
|
||
{
|
||
// Arrange - 模拟PHP API返回的格式
|
||
// PHP: return ['status' => 1, 'data' => $res];
|
||
// $res = ['appId' => ..., 'timeStamp' => ..., 'nonceStr' => ..., 'package' => ..., 'signType' => ..., 'paySign' => ...]
|
||
var result = new WechatPayResult
|
||
{
|
||
Status = 1,
|
||
Msg = "success",
|
||
Data = new WechatPayData
|
||
{
|
||
AppId = "wx1234567890abcdef",
|
||
TimeStamp = "1735776000",
|
||
NonceStr = "abc123def456",
|
||
Package = "prepay_id=wx123456789",
|
||
SignType = "MD5",
|
||
PaySign = "ABCDEF1234567890",
|
||
IsWeixin = 1
|
||
}
|
||
};
|
||
|
||
// Act
|
||
var json = JsonSerializer.Serialize(result, _jsonOptions);
|
||
|
||
// Assert - 验证顶层结构
|
||
Assert.Contains("\"status\":1", json);
|
||
Assert.Contains("\"msg\":\"success\"", json);
|
||
Assert.Contains("\"data\":", json);
|
||
|
||
// Assert - 验证支付参数字段名(与PHP一致)
|
||
Assert.Contains("\"appId\":\"wx1234567890abcdef\"", json);
|
||
Assert.Contains("\"timeStamp\":\"1735776000\"", json);
|
||
Assert.Contains("\"nonceStr\":\"abc123def456\"", json);
|
||
Assert.Contains("\"package\":\"prepay_id=wx123456789\"", json);
|
||
Assert.Contains("\"signType\":\"MD5\"", json);
|
||
Assert.Contains("\"paySign\":\"ABCDEF1234567890\"", json);
|
||
Assert.Contains("\"is_weixin\":1", json);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 验证微信支付失败响应格式
|
||
/// Requirements: 10.1, 10.3
|
||
/// </summary>
|
||
[Fact]
|
||
public void WechatPayFailResponse_ShouldMatchPhpFormat()
|
||
{
|
||
// Arrange - 模拟PHP API返回的失败格式
|
||
// PHP: return ['status' => 0, 'msg' => '支付失败'];
|
||
var result = new WechatPayResult
|
||
{
|
||
Status = 0,
|
||
Msg = "网络故障,请稍后重试(支付参数错误)"
|
||
};
|
||
|
||
// Act
|
||
var json = JsonSerializer.Serialize(result, _jsonOptions);
|
||
|
||
// Assert - 验证结构正确(不验证具体中文内容,因为JSON会转义Unicode)
|
||
Assert.Contains("\"status\":0", json);
|
||
Assert.Contains("\"msg\":", json);
|
||
// data字段应该为null
|
||
Assert.Contains("\"data\":null", json);
|
||
|
||
// 验证反序列化后内容正确
|
||
var deserialized = JsonSerializer.Deserialize<WechatPayResult>(json, _jsonOptions);
|
||
Assert.NotNull(deserialized);
|
||
Assert.Equal(0, deserialized.Status);
|
||
Assert.Equal("网络故障,请稍后重试(支付参数错误)", deserialized.Msg);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 验证支付回调XML响应格式
|
||
/// Requirements: 10.1
|
||
/// </summary>
|
||
[Fact]
|
||
public void NotifyXmlResponse_ShouldMatchWechatFormat()
|
||
{
|
||
// Arrange - 微信要求的XML响应格式
|
||
var successXml = "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";
|
||
var failXml = "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[签名失败]]></return_msg></xml>";
|
||
|
||
// Assert - 验证XML格式正确
|
||
Assert.Contains("<return_code><![CDATA[SUCCESS]]></return_code>", successXml);
|
||
Assert.Contains("<return_msg><![CDATA[OK]]></return_msg>", successXml);
|
||
Assert.Contains("<return_code><![CDATA[FAIL]]></return_code>", failXml);
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region Lottery System Response Format Tests - Requirements 10.1-10.4
|
||
|
||
/// <summary>
|
||
/// 验证PrizeOrderLogRequest使用snake_case
|
||
/// Requirements: 10.2
|
||
/// </summary>
|
||
[Fact]
|
||
public void LotteryPrizeOrderLogRequest_ShouldUseSnakeCase()
|
||
{
|
||
// Arrange
|
||
var request = new HoneyBox.Model.Models.Lottery.PrizeOrderLogRequest
|
||
{
|
||
OrderNum = "TEST001"
|
||
};
|
||
|
||
// Act
|
||
var json = JsonSerializer.Serialize(request, _jsonOptions);
|
||
|
||
// Assert
|
||
Assert.Contains("\"order_num\":", json);
|
||
Assert.DoesNotContain("\"OrderNum\":", json);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 验证InfiniteShangLogRequest使用snake_case
|
||
/// Requirements: 10.2
|
||
/// </summary>
|
||
[Fact]
|
||
public void InfiniteShangLogRequest_ShouldUseSnakeCase()
|
||
{
|
||
// Arrange
|
||
var request = new InfiniteShangLogRequest
|
||
{
|
||
GoodsId = 1,
|
||
ShangId = 10,
|
||
IsMibao = 0,
|
||
Page = 1,
|
||
PageSize = 10
|
||
};
|
||
|
||
// Act
|
||
var json = JsonSerializer.Serialize(request, _jsonOptions);
|
||
|
||
// Assert
|
||
Assert.Contains("\"goods_id\":", json);
|
||
Assert.Contains("\"shang_id\":", json);
|
||
Assert.Contains("\"is_mibao\":", json);
|
||
Assert.Contains("\"page\":", json);
|
||
Assert.Contains("\"page_size\":", json);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 验证DailyPrizeRecordsRequest使用snake_case
|
||
/// Requirements: 10.2
|
||
/// </summary>
|
||
[Fact]
|
||
public void DailyPrizeRecordsRequest_ShouldUseSnakeCase()
|
||
{
|
||
// Arrange
|
||
var request = new DailyPrizeRecordsRequest
|
||
{
|
||
GoodsId = 1,
|
||
Page = 1,
|
||
PageSize = 10
|
||
};
|
||
|
||
// Act
|
||
var json = JsonSerializer.Serialize(request, _jsonOptions);
|
||
|
||
// Assert
|
||
Assert.Contains("\"goods_id\":", json);
|
||
Assert.Contains("\"page\":", json);
|
||
Assert.Contains("\"page_size\":", json);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 验证ItemCardDrawRequest使用snake_case
|
||
/// Requirements: 10.2
|
||
/// </summary>
|
||
[Fact]
|
||
public void ItemCardDrawRequest_ShouldUseSnakeCase()
|
||
{
|
||
// Arrange
|
||
var request = new ItemCardDrawRequest
|
||
{
|
||
GoodsId = 1,
|
||
OrderListIds = "1,2,3"
|
||
};
|
||
|
||
// Act
|
||
var json = JsonSerializer.Serialize(request, _jsonOptions);
|
||
|
||
// Assert
|
||
Assert.Contains("\"goods_id\":", json);
|
||
Assert.Contains("\"order_list_ids\":", json);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 验证InfiniteShangLogResponseDto使用snake_case
|
||
/// Requirements: 10.2
|
||
/// </summary>
|
||
[Fact]
|
||
public void InfiniteShangLogResponseDto_ShouldUseSnakeCase()
|
||
{
|
||
// Arrange
|
||
var dto = new InfiniteShangLogResponseDto
|
||
{
|
||
Category = new List<ShangCategoryDto>
|
||
{
|
||
new() { ShangId = 0, ShangTitle = "全部" },
|
||
new() { ShangId = 10, ShangTitle = "A赏" }
|
||
},
|
||
Data = new List<InfiniteShangLogItemDto>(),
|
||
LastPage = 1,
|
||
Total = 10
|
||
};
|
||
|
||
// Act
|
||
var json = JsonSerializer.Serialize(dto, _jsonOptions);
|
||
|
||
// Assert
|
||
Assert.Contains("\"category\":", json);
|
||
Assert.Contains("\"data\":", json);
|
||
Assert.Contains("\"last_page\":", json);
|
||
Assert.Contains("\"total\":", json);
|
||
Assert.Contains("\"shang_id\":", json);
|
||
Assert.Contains("\"shang_title\":", json);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 验证InfiniteShangLogItemDto使用snake_case
|
||
/// Requirements: 10.2
|
||
/// </summary>
|
||
[Fact]
|
||
public void InfiniteShangLogItemDto_ShouldUseSnakeCase()
|
||
{
|
||
// Arrange
|
||
var dto = new InfiniteShangLogItemDto
|
||
{
|
||
Id = 1,
|
||
UserId = 1,
|
||
GoodslistTitle = "测试奖品",
|
||
GoodslistImgurl = "http://test.com/img.jpg",
|
||
GoodslistPrice = "100.00",
|
||
GoodslistMoney = "50.00",
|
||
ShangId = 10,
|
||
ShangTitle = "A赏",
|
||
ShangColor = "#FF0000",
|
||
PrizeNum = 1,
|
||
Addtime = "2024-01-01 12:00:00",
|
||
LuckNo = 1,
|
||
Doubling = 1,
|
||
IsLingzhu = 0,
|
||
UserInfo = new LotteryUserInfoDto
|
||
{
|
||
Nickname = "测***户",
|
||
HeadImg = "avatar.jpg"
|
||
}
|
||
};
|
||
|
||
// Act
|
||
var json = JsonSerializer.Serialize(dto, _jsonOptions);
|
||
|
||
// Assert
|
||
Assert.Contains("\"id\":", json);
|
||
Assert.Contains("\"user_id\":", json);
|
||
Assert.Contains("\"goodslist_title\":", json);
|
||
Assert.Contains("\"goodslist_imgurl\":", json);
|
||
Assert.Contains("\"goodslist_price\":", json);
|
||
Assert.Contains("\"goodslist_money\":", json);
|
||
Assert.Contains("\"shang_id\":", json);
|
||
Assert.Contains("\"shang_title\":", json);
|
||
Assert.Contains("\"shang_color\":", json);
|
||
Assert.Contains("\"prize_num\":", json);
|
||
Assert.Contains("\"addtime\":", json);
|
||
Assert.Contains("\"luck_no\":", json);
|
||
Assert.Contains("\"doubling\":", json);
|
||
Assert.Contains("\"is_lingzhu\":", json);
|
||
Assert.Contains("\"user_info\":", json);
|
||
Assert.Contains("\"nickname\":", json);
|
||
Assert.Contains("\"headimg\":", json);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 验证DailyPrizeRecordItemDto使用snake_case
|
||
/// Requirements: 10.2
|
||
/// </summary>
|
||
[Fact]
|
||
public void DailyPrizeRecordItemDto_ShouldUseSnakeCase()
|
||
{
|
||
// Arrange
|
||
var dto = new DailyPrizeRecordItemDto
|
||
{
|
||
Id = 1,
|
||
UserId = 1,
|
||
GoodslistTitle = "测试奖品",
|
||
GoodslistImgurl = "http://test.com/img.jpg",
|
||
ShangId = 10,
|
||
ShangTitle = "A赏",
|
||
Addtime = "2024-01-01 12:00:00"
|
||
};
|
||
|
||
// Act
|
||
var json = JsonSerializer.Serialize(dto, _jsonOptions);
|
||
|
||
// Assert
|
||
Assert.Contains("\"id\":", json);
|
||
Assert.Contains("\"user_id\":", json);
|
||
Assert.Contains("\"goodslist_title\":", json);
|
||
Assert.Contains("\"goodslist_imgurl\":", json);
|
||
Assert.Contains("\"shang_id\":", json);
|
||
Assert.Contains("\"shang_title\":", json);
|
||
Assert.Contains("\"addtime\":", json);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 验证InfinitePrizeRecordsResponseDto使用snake_case
|
||
/// Requirements: 10.2
|
||
/// </summary>
|
||
[Fact]
|
||
public void InfinitePrizeRecordsResponseDto_ShouldUseSnakeCase()
|
||
{
|
||
// Arrange
|
||
var dto = new InfinitePrizeRecordsResponseDto
|
||
{
|
||
Data = new List<InfinitePrizeRecordItemDto>(),
|
||
CurrentPage = 1,
|
||
LastPage = 10,
|
||
PerPage = 10,
|
||
Total = 100
|
||
};
|
||
|
||
// Act
|
||
var json = JsonSerializer.Serialize(dto, _jsonOptions);
|
||
|
||
// Assert
|
||
Assert.Contains("\"data\":", json);
|
||
Assert.Contains("\"current_page\":", json);
|
||
Assert.Contains("\"last_page\":", json);
|
||
Assert.Contains("\"per_page\":", json);
|
||
Assert.Contains("\"total\":", json);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 验证InfinitePrizeRecordItemDto使用snake_case
|
||
/// Requirements: 10.2
|
||
/// </summary>
|
||
[Fact]
|
||
public void InfinitePrizeRecordItemDto_ShouldUseSnakeCase()
|
||
{
|
||
// Arrange
|
||
var dto = new InfinitePrizeRecordItemDto
|
||
{
|
||
UserId = 1,
|
||
GoodslistTitle = "测试奖品",
|
||
GoodslistImgurl = "http://test.com/img.jpg",
|
||
Addtime = "2024-01-01 12:00:00"
|
||
};
|
||
|
||
// Act
|
||
var json = JsonSerializer.Serialize(dto, _jsonOptions);
|
||
|
||
// Assert
|
||
Assert.Contains("\"user_id\":", json);
|
||
Assert.Contains("\"goodslist_title\":", json);
|
||
Assert.Contains("\"goodslist_imgurl\":", json);
|
||
Assert.Contains("\"addtime\":", json);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 验证ItemCardDrawResponseDto使用snake_case
|
||
/// Requirements: 10.2
|
||
/// </summary>
|
||
[Fact]
|
||
public void ItemCardDrawResponseDto_ShouldUseSnakeCase()
|
||
{
|
||
// Arrange
|
||
var dto = new ItemCardDrawResponseDto
|
||
{
|
||
Status = 0,
|
||
OrderNum = "TEST001",
|
||
Prizes = new List<ItemCardDrawPrizeDto>
|
||
{
|
||
new()
|
||
{
|
||
Id = 1,
|
||
Title = "测试奖品",
|
||
ImgUrl = "http://test.com/img.jpg",
|
||
ShangId = 10,
|
||
ShangTitle = "A赏",
|
||
ShangColor = "#FF0000",
|
||
Price = "100.00",
|
||
ScMoney = "50.00",
|
||
PrizeCode = "PRIZE001",
|
||
LuckNo = 1
|
||
}
|
||
},
|
||
RemainingCards = 5
|
||
};
|
||
|
||
// Act
|
||
var json = JsonSerializer.Serialize(dto, _jsonOptions);
|
||
|
||
// Assert
|
||
Assert.Contains("\"status\":", json);
|
||
Assert.Contains("\"order_num\":", json);
|
||
Assert.Contains("\"prizes\":", json);
|
||
Assert.Contains("\"remaining_cards\":", json);
|
||
Assert.Contains("\"id\":", json);
|
||
Assert.Contains("\"title\":", json);
|
||
Assert.Contains("\"img_url\":", json);
|
||
Assert.Contains("\"shang_id\":", json);
|
||
Assert.Contains("\"shang_title\":", json);
|
||
Assert.Contains("\"shang_color\":", json);
|
||
Assert.Contains("\"price\":", json);
|
||
Assert.Contains("\"sc_money\":", json);
|
||
Assert.Contains("\"prize_code\":", json);
|
||
Assert.Contains("\"luck_no\":", json);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 验证PrizeOrderLogResponseDto使用snake_case
|
||
/// Requirements: 10.2
|
||
/// </summary>
|
||
[Fact]
|
||
public void PrizeOrderLogResponseDto_ShouldUseSnakeCase()
|
||
{
|
||
// Arrange
|
||
var dto = new PrizeOrderLogResponseDto
|
||
{
|
||
Data = new List<PrizeOrderLogDto>
|
||
{
|
||
new()
|
||
{
|
||
Id = 1,
|
||
UserId = 1,
|
||
GoodsListTitle = "测试奖品",
|
||
GoodsListImgUrl = "http://test.com/img.jpg",
|
||
GoodsListPrice = "100.00",
|
||
GoodsListMoney = "50.00",
|
||
Status = 0,
|
||
LuckNo = 1,
|
||
ShangId = 10,
|
||
ShangTitle = "A赏",
|
||
Doubling = 1,
|
||
IsLingzhu = 0,
|
||
GoodsListType = 1,
|
||
GoodsListId = 1,
|
||
ParentGoodsListId = 0,
|
||
PrizeNum = 1,
|
||
AddTime = 1234567890
|
||
}
|
||
},
|
||
ItemCardCount = 5,
|
||
PrizeNum = 1
|
||
};
|
||
|
||
// Act
|
||
var json = JsonSerializer.Serialize(dto, _jsonOptions);
|
||
|
||
// Assert
|
||
Assert.Contains("\"data\":", json);
|
||
Assert.Contains("\"item_card_count\":", json);
|
||
Assert.Contains("\"prize_num\":", json);
|
||
Assert.Contains("\"id\":", json);
|
||
Assert.Contains("\"user_id\":", json);
|
||
Assert.Contains("\"goodslist_title\":", json);
|
||
Assert.Contains("\"goodslist_imgurl\":", json);
|
||
Assert.Contains("\"goodslist_price\":", json);
|
||
Assert.Contains("\"goodslist_money\":", json);
|
||
Assert.Contains("\"status\":", json);
|
||
Assert.Contains("\"luck_no\":", json);
|
||
Assert.Contains("\"shang_id\":", json);
|
||
Assert.Contains("\"shang_title\":", json);
|
||
Assert.Contains("\"doubling\":", json);
|
||
Assert.Contains("\"is_lingzhu\":", json);
|
||
Assert.Contains("\"goodslist_type\":", json);
|
||
Assert.Contains("\"goodslist_id\":", json);
|
||
Assert.Contains("\"parent_goods_list_id\":", json);
|
||
Assert.Contains("\"addtime\":", json);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 验证InfinitePrizeOrderLogResponseDto使用snake_case
|
||
/// Requirements: 10.2
|
||
/// </summary>
|
||
[Fact]
|
||
public void InfinitePrizeOrderLogResponseDto_ShouldUseSnakeCase()
|
||
{
|
||
// Arrange
|
||
var dto = new InfinitePrizeOrderLogResponseDto
|
||
{
|
||
UserInfo = new UserBasicInfoDto
|
||
{
|
||
Nickname = "测试用户",
|
||
HeadImg = "avatar.jpg"
|
||
},
|
||
Data = new List<PrizeOrderLogDto>(),
|
||
ItemCardCount = 5,
|
||
PrizeNum = 1
|
||
};
|
||
|
||
// Act
|
||
var json = JsonSerializer.Serialize(dto, _jsonOptions);
|
||
|
||
// Assert
|
||
Assert.Contains("\"user_info\":", json);
|
||
Assert.Contains("\"data\":", json);
|
||
Assert.Contains("\"item_card_count\":", json);
|
||
Assert.Contains("\"prize_num\":", json);
|
||
Assert.Contains("\"nickname\":", json);
|
||
Assert.Contains("\"headimg\":", json);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 验证完整的无限赏中奖记录响应格式与PHP API一致
|
||
/// Requirements: 10.1-10.4
|
||
/// </summary>
|
||
[Fact]
|
||
public void CompleteInfiniteShangLogResponse_ShouldMatchPhpFormat()
|
||
{
|
||
// Arrange - 模拟PHP API返回的格式
|
||
var data = new InfiniteShangLogResponseDto
|
||
{
|
||
Category = new List<ShangCategoryDto>
|
||
{
|
||
new() { ShangId = 0, ShangTitle = "全部" },
|
||
new() { ShangId = 10, ShangTitle = "A赏" }
|
||
},
|
||
Data = new List<InfiniteShangLogItemDto>
|
||
{
|
||
new()
|
||
{
|
||
Id = 1,
|
||
UserId = 1,
|
||
GoodslistTitle = "测试奖品",
|
||
GoodslistImgurl = "http://test.com/img.jpg",
|
||
GoodslistPrice = "100.00",
|
||
GoodslistMoney = "50.00",
|
||
ShangId = 10,
|
||
ShangTitle = "A赏",
|
||
ShangColor = "#FF0000",
|
||
PrizeNum = 1,
|
||
Addtime = "2024-01-01 12:00:00",
|
||
LuckNo = 1,
|
||
Doubling = 1,
|
||
IsLingzhu = 0,
|
||
UserInfo = new LotteryUserInfoDto
|
||
{
|
||
Nickname = "测***户",
|
||
HeadImg = "avatar.jpg"
|
||
}
|
||
}
|
||
},
|
||
LastPage = 1,
|
||
Total = 1
|
||
};
|
||
var response = ApiResponse<InfiniteShangLogResponseDto>.Success(data);
|
||
|
||
// Act
|
||
var json = JsonSerializer.Serialize(response, _jsonOptions);
|
||
|
||
// Assert - 验证顶层结构
|
||
Assert.Contains("\"status\":1", json);
|
||
Assert.Contains("\"msg\":\"success\"", json);
|
||
Assert.Contains("\"data\":", json);
|
||
|
||
// Assert - 验证数据字段使用snake_case
|
||
Assert.Contains("\"category\":", json);
|
||
Assert.Contains("\"last_page\":", json);
|
||
Assert.Contains("\"total\":", json);
|
||
Assert.Contains("\"shang_id\":", json);
|
||
Assert.Contains("\"shang_title\":", json);
|
||
Assert.Contains("\"user_id\":", json);
|
||
Assert.Contains("\"goodslist_title\":", json);
|
||
Assert.Contains("\"goodslist_imgurl\":", json);
|
||
Assert.Contains("\"goodslist_price\":", json);
|
||
Assert.Contains("\"goodslist_money\":", json);
|
||
Assert.Contains("\"shang_color\":", json);
|
||
Assert.Contains("\"prize_num\":", json);
|
||
Assert.Contains("\"addtime\":", json);
|
||
Assert.Contains("\"luck_no\":", json);
|
||
Assert.Contains("\"doubling\":", json);
|
||
Assert.Contains("\"is_lingzhu\":", json);
|
||
Assert.Contains("\"user_info\":", json);
|
||
Assert.Contains("\"nickname\":", json);
|
||
Assert.Contains("\"headimg\":", json);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 验证完整的道具卡抽奖响应格式与PHP API一致
|
||
/// Requirements: 10.1-10.4
|
||
/// </summary>
|
||
[Fact]
|
||
public void CompleteItemCardDrawResponse_ShouldMatchPhpFormat()
|
||
{
|
||
// Arrange
|
||
var data = new ItemCardDrawResponseDto
|
||
{
|
||
Status = 0,
|
||
OrderNum = "MH_20240101120000001",
|
||
Prizes = new List<ItemCardDrawPrizeDto>
|
||
{
|
||
new()
|
||
{
|
||
Id = 1,
|
||
Title = "A赏奖品",
|
||
ImgUrl = "http://test.com/prize.jpg",
|
||
ShangId = 10,
|
||
ShangTitle = "A赏",
|
||
ShangColor = "#FF0000",
|
||
Price = "100.00",
|
||
ScMoney = "50.00",
|
||
PrizeCode = "PRIZE20240101001",
|
||
LuckNo = 88
|
||
}
|
||
},
|
||
RemainingCards = 4
|
||
};
|
||
var response = ApiResponse<ItemCardDrawResponseDto>.Success(data, "重抽成功");
|
||
|
||
// Act
|
||
var json = JsonSerializer.Serialize(response, _jsonOptions);
|
||
|
||
// Assert - 验证顶层结构
|
||
Assert.Contains("\"status\":1", json);
|
||
Assert.Contains("\"data\":", json);
|
||
|
||
// Assert - 验证数据字段使用snake_case
|
||
Assert.Contains("\"order_num\":", json);
|
||
Assert.Contains("\"prizes\":", json);
|
||
Assert.Contains("\"remaining_cards\":", json);
|
||
Assert.Contains("\"img_url\":", json);
|
||
Assert.Contains("\"shang_id\":", json);
|
||
Assert.Contains("\"shang_title\":", json);
|
||
Assert.Contains("\"shang_color\":", json);
|
||
Assert.Contains("\"sc_money\":", json);
|
||
Assert.Contains("\"prize_code\":", json);
|
||
Assert.Contains("\"luck_no\":", json);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 验证抽奖系统失败响应格式
|
||
/// Requirements: 10.1, 10.3
|
||
/// </summary>
|
||
[Fact]
|
||
public void LotteryFailResponse_ShouldMatchPhpFormat()
|
||
{
|
||
// Arrange - 模拟PHP API返回的失败格式
|
||
var response = ApiResponse<InfiniteShangLogResponseDto>.Fail("盒子不存在");
|
||
|
||
// Act
|
||
var json = JsonSerializer.Serialize(response, _jsonOptions);
|
||
|
||
// Assert
|
||
Assert.Contains("\"status\":0", json);
|
||
Assert.Contains("\"msg\":", json);
|
||
|
||
// 验证反序列化后内容正确
|
||
var deserialized = JsonSerializer.Deserialize<ApiResponse<InfiniteShangLogResponseDto>>(json, _jsonOptions);
|
||
Assert.NotNull(deserialized);
|
||
Assert.Equal(0, deserialized.Status);
|
||
Assert.Equal("盒子不存在", deserialized.Msg);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 验证ShangInfoDto使用snake_case(用于赏品等级信息)
|
||
/// Requirements: 10.2
|
||
/// </summary>
|
||
[Fact]
|
||
public void ShangInfoDto_ShouldUseSnakeCase()
|
||
{
|
||
// Arrange
|
||
var dto = new ShangInfoDto
|
||
{
|
||
Id = 10,
|
||
Title = "A赏",
|
||
ImgUrl = "http://test.com/shang.jpg",
|
||
Color = "#FF0000",
|
||
SpecialImgUrl = "http://test.com/special.jpg"
|
||
};
|
||
|
||
// Act
|
||
var json = JsonSerializer.Serialize(dto, _jsonOptions);
|
||
|
||
// Assert
|
||
Assert.Contains("\"id\":", json);
|
||
Assert.Contains("\"title\":", json);
|
||
Assert.Contains("\"img_url\":", json);
|
||
Assert.Contains("\"color\":", json);
|
||
Assert.Contains("\"special_img_url\":", json);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 验证LotteryUserInfoDto使用snake_case
|
||
/// Requirements: 10.2
|
||
/// </summary>
|
||
[Fact]
|
||
public void LotteryUserInfoDto_ShouldUseSnakeCase()
|
||
{
|
||
// Arrange
|
||
var dto = new LotteryUserInfoDto
|
||
{
|
||
Nickname = "测***户",
|
||
HeadImg = "avatar.jpg"
|
||
};
|
||
|
||
// Act
|
||
var json = JsonSerializer.Serialize(dto, _jsonOptions);
|
||
|
||
// Assert
|
||
Assert.Contains("\"nickname\":", json);
|
||
Assert.Contains("\"headimg\":", json);
|
||
}
|
||
|
||
#endregion
|
||
}
|