331 lines
11 KiB
C#
331 lines
11 KiB
C#
using HoneyBox.Core.Interfaces;
|
|
using HoneyBox.Core.Services;
|
|
using HoneyBox.Model.Models.Auth;
|
|
using HoneyBox.Model.Models.Payment;
|
|
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 WechatSettings _wechatSettings;
|
|
private readonly Mock<IOptions<WechatPaySettings>> _mockWechatPaySettings;
|
|
private readonly Mock<IRedisService> _mockRedisService;
|
|
|
|
public WechatServiceTests()
|
|
{
|
|
_mockLogger = new Mock<ILogger<WechatService>>();
|
|
_wechatSettings = new WechatSettings
|
|
{
|
|
AppId = "test_app_id",
|
|
AppSecret = "test_app_secret"
|
|
};
|
|
|
|
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>();
|
|
}
|
|
|
|
[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 wechatService = new WechatService(httpClient, _mockLogger.Object, _wechatSettings, _mockWechatPaySettings.Object, _mockRedisService.Object);
|
|
|
|
// 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 wechatService = new WechatService(httpClient, _mockLogger.Object, _wechatSettings, _mockWechatPaySettings.Object, _mockRedisService.Object);
|
|
|
|
// 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 wechatService = new WechatService(httpClient, _mockLogger.Object, _wechatSettings, _mockWechatPaySettings.Object, _mockRedisService.Object);
|
|
|
|
// 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 wechatService = new WechatService(httpClient, _mockLogger.Object, _wechatSettings, _mockWechatPaySettings.Object, _mockRedisService.Object);
|
|
|
|
// 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 wechatService = new WechatService(httpClient, _mockLogger.Object, _wechatSettings, _mockWechatPaySettings.Object, _mockRedisService.Object);
|
|
|
|
// 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 wechatService = new WechatService(httpClient, _mockLogger.Object, _wechatSettings, _mockWechatPaySettings.Object, _mockRedisService.Object);
|
|
|
|
// 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 wechatService = new WechatService(httpClient, _mockLogger.Object, _wechatSettings, _mockWechatPaySettings.Object, _mockRedisService.Object);
|
|
|
|
// 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 wechatService = new WechatService(httpClient, _mockLogger.Object, _wechatSettings, _mockWechatPaySettings.Object, _mockRedisService.Object);
|
|
|
|
// 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 wechatService = new WechatService(httpClient, _mockLogger.Object, _wechatSettings, _mockWechatPaySettings.Object, _mockRedisService.Object);
|
|
|
|
// 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()
|
|
{
|
|
// Act & Assert
|
|
Assert.Throws<ArgumentNullException>(() =>
|
|
new WechatService(null!, _mockLogger.Object, _wechatSettings, _mockWechatPaySettings.Object, _mockRedisService.Object));
|
|
}
|
|
|
|
[Fact]
|
|
public void WechatService_WithNullLogger_ThrowsArgumentNullException()
|
|
{
|
|
// Arrange
|
|
var httpClient = new HttpClient();
|
|
|
|
// Act & Assert
|
|
Assert.Throws<ArgumentNullException>(() =>
|
|
new WechatService(httpClient, null!, _wechatSettings, _mockWechatPaySettings.Object, _mockRedisService.Object));
|
|
}
|
|
|
|
[Fact]
|
|
public void WechatService_WithNullWechatSettings_ThrowsArgumentNullException()
|
|
{
|
|
// Arrange
|
|
var httpClient = new HttpClient();
|
|
|
|
// Act & Assert
|
|
Assert.Throws<ArgumentNullException>(() =>
|
|
new WechatService(httpClient, _mockLogger.Object, null!, _mockWechatPaySettings.Object, _mockRedisService.Object));
|
|
}
|
|
}
|