HaniBlindBox/server/HoneyBox/tests/HoneyBox.Tests/Services/WechatServiceTests.cs
2026-02-01 19:30:51 +08:00

350 lines
11 KiB
C#

using HoneyBox.Core.Interfaces;
using HoneyBox.Core.Services;
using HoneyBox.Model.Data;
using HoneyBox.Model.Models.Auth;
using HoneyBox.Model.Models.Payment;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Moq;
using Xunit;
namespace HoneyBox.Tests.Services;
/// <summary>
/// Mock HttpMessageHandler for testing
/// </summary>
public class MockHttpMessageHandler : HttpMessageHandler
{
private readonly Func<HttpRequestMessage, Task<HttpResponseMessage>> _handler;
public MockHttpMessageHandler(Func<HttpRequestMessage, Task<HttpResponseMessage>> handler)
{
_handler = handler;
}
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
return await _handler(request);
}
}
public class WechatServiceTests
{
private readonly Mock<ILogger<WechatService>> _mockLogger;
private readonly Mock<IOptions<WechatPaySettings>> _mockWechatPaySettings;
private readonly Mock<IRedisService> _mockRedisService;
public WechatServiceTests()
{
_mockLogger = new Mock<ILogger<WechatService>>();
var wechatPaySettings = new WechatPaySettings
{
DefaultMerchant = new WechatPayMerchantConfig
{
Name = "TestMerchant",
MchId = "1234567890",
AppId = "wx1234567890abcdef",
Key = "test_secret_key_32_characters_ok",
OrderPrefix = "TST",
Weight = 1,
NotifyUrl = "https://example.com/notify"
},
Merchants = new List<WechatPayMerchantConfig>()
};
_mockWechatPaySettings = new Mock<IOptions<WechatPaySettings>>();
_mockWechatPaySettings.Setup(x => x.Value).Returns(wechatPaySettings);
_mockRedisService = new Mock<IRedisService>();
}
private HoneyBoxDbContext CreateInMemoryDbContext()
{
var options = new DbContextOptionsBuilder<HoneyBoxDbContext>()
.UseInMemoryDatabase(databaseName: Guid.NewGuid().ToString())
.Options;
return new HoneyBoxDbContext(options);
}
[Fact]
public async Task GetOpenIdAsync_WithValidCode_ReturnsSuccessResult()
{
// Arrange
var responseContent = @"{
""session_key"": ""test_session_key"",
""openid"": ""test_openid_123"",
""unionid"": ""test_unionid_456""
}";
var handler = new MockHttpMessageHandler(async request =>
{
return new HttpResponseMessage
{
StatusCode = System.Net.HttpStatusCode.OK,
Content = new StringContent(responseContent)
};
});
var httpClient = new HttpClient(handler);
var dbContext = CreateInMemoryDbContext();
var wechatService = new WechatService(httpClient, _mockLogger.Object, _mockWechatPaySettings.Object, _mockRedisService.Object, dbContext);
// Act
var result = await wechatService.GetOpenIdAsync("test_code");
// Assert
Assert.NotNull(result);
Assert.True(result.Success);
Assert.Equal("test_openid_123", result.OpenId);
Assert.Equal("test_unionid_456", result.UnionId);
Assert.Null(result.ErrorMessage);
}
[Fact]
public async Task GetOpenIdAsync_WithEmptyCode_ReturnsFailureResult()
{
// Arrange
var httpClient = new HttpClient();
var dbContext = CreateInMemoryDbContext();
var wechatService = new WechatService(httpClient, _mockLogger.Object, _mockWechatPaySettings.Object, _mockRedisService.Object, dbContext);
// Act
var result = await wechatService.GetOpenIdAsync(string.Empty);
// Assert
Assert.NotNull(result);
Assert.False(result.Success);
Assert.Null(result.OpenId);
Assert.NotNull(result.ErrorMessage);
}
[Fact]
public async Task GetOpenIdAsync_WithNullCode_ReturnsFailureResult()
{
// Arrange
var httpClient = new HttpClient();
var dbContext = CreateInMemoryDbContext();
var wechatService = new WechatService(httpClient, _mockLogger.Object, _mockWechatPaySettings.Object, _mockRedisService.Object, dbContext);
// Act
var result = await wechatService.GetOpenIdAsync(null!);
// Assert
Assert.NotNull(result);
Assert.False(result.Success);
Assert.Null(result.OpenId);
Assert.NotNull(result.ErrorMessage);
}
[Fact]
public async Task GetOpenIdAsync_WithWechatError_ReturnsFailureResult()
{
// Arrange
var responseContent = @"{
""errcode"": 40001,
""errmsg"": ""invalid credential""
}";
var handler = new MockHttpMessageHandler(async request =>
{
return new HttpResponseMessage
{
StatusCode = System.Net.HttpStatusCode.OK,
Content = new StringContent(responseContent)
};
});
var httpClient = new HttpClient(handler);
var dbContext = CreateInMemoryDbContext();
var wechatService = new WechatService(httpClient, _mockLogger.Object, _mockWechatPaySettings.Object, _mockRedisService.Object, dbContext);
// Act
var result = await wechatService.GetOpenIdAsync("invalid_code");
// Assert
Assert.NotNull(result);
Assert.False(result.Success);
Assert.Null(result.OpenId);
Assert.NotNull(result.ErrorMessage);
Assert.Contains("invalid credential", result.ErrorMessage);
}
[Fact]
public async Task GetOpenIdAsync_WithHttpError_ReturnsFailureResult()
{
// Arrange
var handler = new MockHttpMessageHandler(async request =>
{
return new HttpResponseMessage
{
StatusCode = System.Net.HttpStatusCode.InternalServerError,
Content = new StringContent("Server Error")
};
});
var httpClient = new HttpClient(handler);
var dbContext = CreateInMemoryDbContext();
var wechatService = new WechatService(httpClient, _mockLogger.Object, _mockWechatPaySettings.Object, _mockRedisService.Object, dbContext);
// Act
var result = await wechatService.GetOpenIdAsync("test_code");
// Assert
Assert.NotNull(result);
Assert.False(result.Success);
Assert.Null(result.OpenId);
Assert.NotNull(result.ErrorMessage);
}
[Fact]
public async Task GetMobileAsync_WithValidCode_ReturnsSuccessResult()
{
// Arrange
var responseContent = @"{
""errcode"": 0,
""errmsg"": ""ok"",
""phone_info"": {
""phoneNumber"": ""13800138000"",
""purePhoneNumber"": ""13800138000"",
""countryCode"": ""86""
}
}";
var handler = new MockHttpMessageHandler(async request =>
{
return new HttpResponseMessage
{
StatusCode = System.Net.HttpStatusCode.OK,
Content = new StringContent(responseContent)
};
});
var httpClient = new HttpClient(handler);
var dbContext = CreateInMemoryDbContext();
var wechatService = new WechatService(httpClient, _mockLogger.Object, _mockWechatPaySettings.Object, _mockRedisService.Object, dbContext);
// Act
var result = await wechatService.GetMobileAsync("test_access_token");
// Assert
Assert.NotNull(result);
Assert.True(result.Success);
Assert.Equal("13800138000", result.Mobile);
Assert.Null(result.ErrorMessage);
}
[Fact]
public async Task GetMobileAsync_WithEmptyCode_ReturnsFailureResult()
{
// Arrange
var httpClient = new HttpClient();
var dbContext = CreateInMemoryDbContext();
var wechatService = new WechatService(httpClient, _mockLogger.Object, _mockWechatPaySettings.Object, _mockRedisService.Object, dbContext);
// Act
var result = await wechatService.GetMobileAsync(string.Empty);
// Assert
Assert.NotNull(result);
Assert.False(result.Success);
Assert.Null(result.Mobile);
Assert.NotNull(result.ErrorMessage);
}
[Fact]
public async Task GetMobileAsync_WithWechatError_ReturnsFailureResult()
{
// Arrange
var responseContent = @"{
""errcode"": 40001,
""errmsg"": ""invalid access_token""
}";
var handler = new MockHttpMessageHandler(async request =>
{
return new HttpResponseMessage
{
StatusCode = System.Net.HttpStatusCode.OK,
Content = new StringContent(responseContent)
};
});
var httpClient = new HttpClient(handler);
var dbContext = CreateInMemoryDbContext();
var wechatService = new WechatService(httpClient, _mockLogger.Object, _mockWechatPaySettings.Object, _mockRedisService.Object, dbContext);
// Act
var result = await wechatService.GetMobileAsync("invalid_token");
// Assert
Assert.NotNull(result);
Assert.False(result.Success);
Assert.Null(result.Mobile);
Assert.NotNull(result.ErrorMessage);
}
[Fact]
public async Task GetMobileAsync_WithHttpError_ReturnsFailureResult()
{
// Arrange
var handler = new MockHttpMessageHandler(async request =>
{
return new HttpResponseMessage
{
StatusCode = System.Net.HttpStatusCode.ServiceUnavailable,
Content = new StringContent("Service Unavailable")
};
});
var httpClient = new HttpClient(handler);
var dbContext = CreateInMemoryDbContext();
var wechatService = new WechatService(httpClient, _mockLogger.Object, _mockWechatPaySettings.Object, _mockRedisService.Object, dbContext);
// Act
var result = await wechatService.GetMobileAsync("test_token");
// Assert
Assert.NotNull(result);
Assert.False(result.Success);
Assert.Null(result.Mobile);
Assert.NotNull(result.ErrorMessage);
}
[Fact]
public void WechatService_WithNullHttpClient_ThrowsArgumentNullException()
{
// Arrange
var dbContext = CreateInMemoryDbContext();
// Act & Assert
Assert.Throws<ArgumentNullException>(() =>
new WechatService(null!, _mockLogger.Object, _mockWechatPaySettings.Object, _mockRedisService.Object, dbContext));
}
[Fact]
public void WechatService_WithNullLogger_ThrowsArgumentNullException()
{
// Arrange
var httpClient = new HttpClient();
var dbContext = CreateInMemoryDbContext();
// Act & Assert
Assert.Throws<ArgumentNullException>(() =>
new WechatService(httpClient, null!, _mockWechatPaySettings.Object, _mockRedisService.Object, dbContext));
}
[Fact]
public void WechatService_WithNullWechatPaySettings_ThrowsArgumentNullException()
{
// Arrange
var httpClient = new HttpClient();
var dbContext = CreateInMemoryDbContext();
// Act & Assert
Assert.Throws<ArgumentNullException>(() =>
new WechatService(httpClient, _mockLogger.Object, null!, _mockRedisService.Object, dbContext));
}
}