546 lines
21 KiB
C#
546 lines
21 KiB
C#
using FsCheck;
|
||
using FsCheck.Xunit;
|
||
using Microsoft.Extensions.Logging;
|
||
using MiAssessment.Core.Interfaces;
|
||
using MiAssessment.Core.Services;
|
||
using MiAssessment.Model.Models.System;
|
||
using Moq;
|
||
using Xunit;
|
||
|
||
namespace MiAssessment.Tests.Services;
|
||
|
||
/// <summary>
|
||
/// SystemService 属性测试
|
||
/// 验证系统配置服务的响应格式一致性
|
||
/// </summary>
|
||
public class SystemServicePropertyTests
|
||
{
|
||
private readonly Mock<ILogger<SystemService>> _mockLogger = new();
|
||
|
||
#region Property 8: 响应格式一致性 - GetAgreementAsync
|
||
|
||
/// <summary>
|
||
/// Property 8: GetAgreementAsync 返回包含 Content 属性的 AgreementDto
|
||
/// *For any* GetAgreementAsync call, the returned AgreementDto SHALL have a Content property.
|
||
///
|
||
/// **Feature: miniapp-api, Property 8: 响应格式一致性**
|
||
/// **Validates: Requirements 14.1, 16.1, 16.2, 16.3**
|
||
/// </summary>
|
||
[Property(MaxTest = 100)]
|
||
public bool GetAgreementAsync_ReturnsAgreementDtoWithContentProperty(NonEmptyString content)
|
||
{
|
||
// Arrange
|
||
var mockConfigService = new Mock<IConfigService>();
|
||
mockConfigService
|
||
.Setup(x => x.GetConfigValueAsync("user_agreement"))
|
||
.ReturnsAsync(content.Get);
|
||
|
||
var service = new SystemService(mockConfigService.Object, _mockLogger.Object);
|
||
|
||
// Act
|
||
var result = service.GetAgreementAsync().GetAwaiter().GetResult();
|
||
|
||
// Assert: 验证返回的 AgreementDto 包含 Content 属性且值正确
|
||
return result != null && result.Content == content.Get;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Property 8: GetAgreementAsync 返回非空 DTO,即使配置值为空
|
||
///
|
||
/// **Feature: miniapp-api, Property 8: 响应格式一致性**
|
||
/// **Validates: Requirements 14.1, 16.1, 16.2, 16.3**
|
||
/// </summary>
|
||
[Fact]
|
||
public void GetAgreementAsync_ReturnsNonNullDto_WhenConfigValueIsNull()
|
||
{
|
||
// Arrange
|
||
var mockConfigService = new Mock<IConfigService>();
|
||
mockConfigService
|
||
.Setup(x => x.GetConfigValueAsync("user_agreement"))
|
||
.ReturnsAsync((string?)null);
|
||
|
||
var service = new SystemService(mockConfigService.Object, _mockLogger.Object);
|
||
|
||
// Act
|
||
var result = service.GetAgreementAsync().GetAwaiter().GetResult();
|
||
|
||
// Assert: 即使配置值为空,也应返回非空 DTO
|
||
Assert.NotNull(result);
|
||
Assert.NotNull(result.Content);
|
||
Assert.Equal(string.Empty, result.Content);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Property 8: GetAgreementAsync 返回非空 DTO,即使配置值为空字符串
|
||
///
|
||
/// **Feature: miniapp-api, Property 8: 响应格式一致性**
|
||
/// **Validates: Requirements 14.1, 16.1, 16.2, 16.3**
|
||
/// </summary>
|
||
[Fact]
|
||
public void GetAgreementAsync_ReturnsNonNullDto_WhenConfigValueIsEmpty()
|
||
{
|
||
// Arrange
|
||
var mockConfigService = new Mock<IConfigService>();
|
||
mockConfigService
|
||
.Setup(x => x.GetConfigValueAsync("user_agreement"))
|
||
.ReturnsAsync(string.Empty);
|
||
|
||
var service = new SystemService(mockConfigService.Object, _mockLogger.Object);
|
||
|
||
// Act
|
||
var result = service.GetAgreementAsync().GetAwaiter().GetResult();
|
||
|
||
// Assert
|
||
Assert.NotNull(result);
|
||
Assert.NotNull(result.Content);
|
||
Assert.Equal(string.Empty, result.Content);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Property 8: GetAgreementAsync 响应格式一致性 - Content 属性始终存在
|
||
///
|
||
/// **Feature: miniapp-api, Property 8: 响应格式一致性**
|
||
/// **Validates: Requirements 14.1, 16.1, 16.2, 16.3**
|
||
/// </summary>
|
||
[Property(MaxTest = 100)]
|
||
public bool GetAgreementAsync_ContentPropertyAlwaysExists(PositiveInt seed)
|
||
{
|
||
// Arrange: 使用不同的配置值
|
||
var configValues = new string?[] { null, "", "协议内容", "用户协议\n第一条...", $"Agreement_{seed.Get}" };
|
||
var configValue = configValues[seed.Get % configValues.Length];
|
||
|
||
var mockConfigService = new Mock<IConfigService>();
|
||
mockConfigService
|
||
.Setup(x => x.GetConfigValueAsync("user_agreement"))
|
||
.ReturnsAsync(configValue);
|
||
|
||
var service = new SystemService(mockConfigService.Object, _mockLogger.Object);
|
||
|
||
// Act
|
||
var result = service.GetAgreementAsync().GetAwaiter().GetResult();
|
||
|
||
// Assert: Content 属性始终存在且不为 null
|
||
return result != null && result.Content != null;
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region Property 8: 响应格式一致性 - GetPrivacyAsync
|
||
|
||
/// <summary>
|
||
/// Property 8: GetPrivacyAsync 返回包含 Content 属性的 PrivacyDto
|
||
/// *For any* GetPrivacyAsync call, the returned PrivacyDto SHALL have a Content property.
|
||
///
|
||
/// **Feature: miniapp-api, Property 8: 响应格式一致性**
|
||
/// **Validates: Requirements 14.2, 16.1, 16.2, 16.3**
|
||
/// </summary>
|
||
[Property(MaxTest = 100)]
|
||
public bool GetPrivacyAsync_ReturnsPrivacyDtoWithContentProperty(NonEmptyString content)
|
||
{
|
||
// Arrange
|
||
var mockConfigService = new Mock<IConfigService>();
|
||
mockConfigService
|
||
.Setup(x => x.GetConfigValueAsync("privacy_policy"))
|
||
.ReturnsAsync(content.Get);
|
||
|
||
var service = new SystemService(mockConfigService.Object, _mockLogger.Object);
|
||
|
||
// Act
|
||
var result = service.GetPrivacyAsync().GetAwaiter().GetResult();
|
||
|
||
// Assert: 验证返回的 PrivacyDto 包含 Content 属性且值正确
|
||
return result != null && result.Content == content.Get;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Property 8: GetPrivacyAsync 返回非空 DTO,即使配置值为空
|
||
///
|
||
/// **Feature: miniapp-api, Property 8: 响应格式一致性**
|
||
/// **Validates: Requirements 14.2, 16.1, 16.2, 16.3**
|
||
/// </summary>
|
||
[Fact]
|
||
public void GetPrivacyAsync_ReturnsNonNullDto_WhenConfigValueIsNull()
|
||
{
|
||
// Arrange
|
||
var mockConfigService = new Mock<IConfigService>();
|
||
mockConfigService
|
||
.Setup(x => x.GetConfigValueAsync("privacy_policy"))
|
||
.ReturnsAsync((string?)null);
|
||
|
||
var service = new SystemService(mockConfigService.Object, _mockLogger.Object);
|
||
|
||
// Act
|
||
var result = service.GetPrivacyAsync().GetAwaiter().GetResult();
|
||
|
||
// Assert: 即使配置值为空,也应返回非空 DTO
|
||
Assert.NotNull(result);
|
||
Assert.NotNull(result.Content);
|
||
Assert.Equal(string.Empty, result.Content);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Property 8: GetPrivacyAsync 返回非空 DTO,即使配置值为空字符串
|
||
///
|
||
/// **Feature: miniapp-api, Property 8: 响应格式一致性**
|
||
/// **Validates: Requirements 14.2, 16.1, 16.2, 16.3**
|
||
/// </summary>
|
||
[Fact]
|
||
public void GetPrivacyAsync_ReturnsNonNullDto_WhenConfigValueIsEmpty()
|
||
{
|
||
// Arrange
|
||
var mockConfigService = new Mock<IConfigService>();
|
||
mockConfigService
|
||
.Setup(x => x.GetConfigValueAsync("privacy_policy"))
|
||
.ReturnsAsync(string.Empty);
|
||
|
||
var service = new SystemService(mockConfigService.Object, _mockLogger.Object);
|
||
|
||
// Act
|
||
var result = service.GetPrivacyAsync().GetAwaiter().GetResult();
|
||
|
||
// Assert
|
||
Assert.NotNull(result);
|
||
Assert.NotNull(result.Content);
|
||
Assert.Equal(string.Empty, result.Content);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Property 8: GetPrivacyAsync 响应格式一致性 - Content 属性始终存在
|
||
///
|
||
/// **Feature: miniapp-api, Property 8: 响应格式一致性**
|
||
/// **Validates: Requirements 14.2, 16.1, 16.2, 16.3**
|
||
/// </summary>
|
||
[Property(MaxTest = 100)]
|
||
public bool GetPrivacyAsync_ContentPropertyAlwaysExists(PositiveInt seed)
|
||
{
|
||
// Arrange: 使用不同的配置值
|
||
var configValues = new string?[] { null, "", "隐私政策", "隐私政策\n第一条...", $"Privacy_{seed.Get}" };
|
||
var configValue = configValues[seed.Get % configValues.Length];
|
||
|
||
var mockConfigService = new Mock<IConfigService>();
|
||
mockConfigService
|
||
.Setup(x => x.GetConfigValueAsync("privacy_policy"))
|
||
.ReturnsAsync(configValue);
|
||
|
||
var service = new SystemService(mockConfigService.Object, _mockLogger.Object);
|
||
|
||
// Act
|
||
var result = service.GetPrivacyAsync().GetAwaiter().GetResult();
|
||
|
||
// Assert: Content 属性始终存在且不为 null
|
||
return result != null && result.Content != null;
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region Property 8: 响应格式一致性 - GetAboutAsync
|
||
|
||
/// <summary>
|
||
/// Property 8: GetAboutAsync 返回包含 Content 和 Version 属性的 AboutDto
|
||
/// *For any* GetAboutAsync call, the returned AboutDto SHALL have Content and Version properties.
|
||
///
|
||
/// **Feature: miniapp-api, Property 8: 响应格式一致性**
|
||
/// **Validates: Requirements 14.3, 16.1, 16.2, 16.3**
|
||
/// </summary>
|
||
[Property(MaxTest = 100)]
|
||
public bool GetAboutAsync_ReturnsAboutDtoWithContentAndVersionProperties(NonEmptyString content, NonEmptyString version)
|
||
{
|
||
// Arrange
|
||
var mockConfigService = new Mock<IConfigService>();
|
||
mockConfigService
|
||
.Setup(x => x.GetConfigValueAsync("about_us"))
|
||
.ReturnsAsync(content.Get);
|
||
mockConfigService
|
||
.Setup(x => x.GetConfigValueAsync("app_version"))
|
||
.ReturnsAsync(version.Get);
|
||
|
||
var service = new SystemService(mockConfigService.Object, _mockLogger.Object);
|
||
|
||
// Act
|
||
var result = service.GetAboutAsync().GetAwaiter().GetResult();
|
||
|
||
// Assert: 验证返回的 AboutDto 包含 Content 和 Version 属性且值正确
|
||
return result != null &&
|
||
result.Content == content.Get &&
|
||
result.Version == version.Get;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Property 8: GetAboutAsync 返回非空 DTO,即使配置值为空
|
||
///
|
||
/// **Feature: miniapp-api, Property 8: 响应格式一致性**
|
||
/// **Validates: Requirements 14.3, 16.1, 16.2, 16.3**
|
||
/// </summary>
|
||
[Fact]
|
||
public void GetAboutAsync_ReturnsNonNullDto_WhenConfigValuesAreNull()
|
||
{
|
||
// Arrange
|
||
var mockConfigService = new Mock<IConfigService>();
|
||
mockConfigService
|
||
.Setup(x => x.GetConfigValueAsync("about_us"))
|
||
.ReturnsAsync((string?)null);
|
||
mockConfigService
|
||
.Setup(x => x.GetConfigValueAsync("app_version"))
|
||
.ReturnsAsync((string?)null);
|
||
|
||
var service = new SystemService(mockConfigService.Object, _mockLogger.Object);
|
||
|
||
// Act
|
||
var result = service.GetAboutAsync().GetAwaiter().GetResult();
|
||
|
||
// Assert: 即使配置值为空,也应返回非空 DTO
|
||
Assert.NotNull(result);
|
||
Assert.NotNull(result.Content);
|
||
Assert.NotNull(result.Version);
|
||
Assert.Equal(string.Empty, result.Content);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Property 8: GetAboutAsync Version 有默认值,当未配置时
|
||
///
|
||
/// **Feature: miniapp-api, Property 8: 响应格式一致性**
|
||
/// **Validates: Requirements 14.3, 16.1, 16.2, 16.3**
|
||
/// </summary>
|
||
[Fact]
|
||
public void GetAboutAsync_VersionHasDefaultValue_WhenNotConfigured()
|
||
{
|
||
// Arrange
|
||
var mockConfigService = new Mock<IConfigService>();
|
||
mockConfigService
|
||
.Setup(x => x.GetConfigValueAsync("about_us"))
|
||
.ReturnsAsync("关于我们内容");
|
||
mockConfigService
|
||
.Setup(x => x.GetConfigValueAsync("app_version"))
|
||
.ReturnsAsync((string?)null);
|
||
|
||
var service = new SystemService(mockConfigService.Object, _mockLogger.Object);
|
||
|
||
// Act
|
||
var result = service.GetAboutAsync().GetAwaiter().GetResult();
|
||
|
||
// Assert: Version 应该有默认值 "1.0.0"
|
||
Assert.NotNull(result);
|
||
Assert.Equal("1.0.0", result.Version);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Property 8: GetAboutAsync Version 有默认值,当配置为空字符串时
|
||
///
|
||
/// **Feature: miniapp-api, Property 8: 响应格式一致性**
|
||
/// **Validates: Requirements 14.3, 16.1, 16.2, 16.3**
|
||
/// </summary>
|
||
[Fact]
|
||
public void GetAboutAsync_VersionHasDefaultValue_WhenConfiguredAsEmpty()
|
||
{
|
||
// Arrange
|
||
var mockConfigService = new Mock<IConfigService>();
|
||
mockConfigService
|
||
.Setup(x => x.GetConfigValueAsync("about_us"))
|
||
.ReturnsAsync("关于我们内容");
|
||
mockConfigService
|
||
.Setup(x => x.GetConfigValueAsync("app_version"))
|
||
.ReturnsAsync(string.Empty);
|
||
|
||
var service = new SystemService(mockConfigService.Object, _mockLogger.Object);
|
||
|
||
// Act
|
||
var result = service.GetAboutAsync().GetAwaiter().GetResult();
|
||
|
||
// Assert: 当配置为空字符串时,应该返回空字符串(不是默认值)
|
||
// 因为 SystemService 只在 null 时使用默认值
|
||
Assert.NotNull(result);
|
||
Assert.Equal(string.Empty, result.Version);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Property 8: GetAboutAsync 响应格式一致性 - Content 和 Version 属性始终存在
|
||
///
|
||
/// **Feature: miniapp-api, Property 8: 响应格式一致性**
|
||
/// **Validates: Requirements 14.3, 16.1, 16.2, 16.3**
|
||
/// </summary>
|
||
[Property(MaxTest = 100)]
|
||
public bool GetAboutAsync_ContentAndVersionPropertiesAlwaysExist(PositiveInt seed)
|
||
{
|
||
// Arrange: 使用不同的配置值组合
|
||
var contentValues = new string?[] { null, "", "关于我们", "公司介绍\n...", $"About_{seed.Get}" };
|
||
var versionValues = new string?[] { null, "", "1.0.0", "2.1.3", $"v{seed.Get % 10}.{seed.Get % 100}.{seed.Get % 1000}" };
|
||
|
||
var contentValue = contentValues[seed.Get % contentValues.Length];
|
||
var versionValue = versionValues[(seed.Get / contentValues.Length) % versionValues.Length];
|
||
|
||
var mockConfigService = new Mock<IConfigService>();
|
||
mockConfigService
|
||
.Setup(x => x.GetConfigValueAsync("about_us"))
|
||
.ReturnsAsync(contentValue);
|
||
mockConfigService
|
||
.Setup(x => x.GetConfigValueAsync("app_version"))
|
||
.ReturnsAsync(versionValue);
|
||
|
||
var service = new SystemService(mockConfigService.Object, _mockLogger.Object);
|
||
|
||
// Act
|
||
var result = service.GetAboutAsync().GetAwaiter().GetResult();
|
||
|
||
// Assert: Content 和 Version 属性始终存在且不为 null
|
||
return result != null && result.Content != null && result.Version != null;
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region 综合属性测试
|
||
|
||
/// <summary>
|
||
/// Property 8: 所有系统配置方法返回非空 DTO
|
||
///
|
||
/// **Feature: miniapp-api, Property 8: 响应格式一致性**
|
||
/// **Validates: Requirements 14.1, 14.2, 14.3, 16.1, 16.2, 16.3**
|
||
/// </summary>
|
||
[Property(MaxTest = 100)]
|
||
public bool AllSystemMethods_ReturnNonNullDtos(PositiveInt seed)
|
||
{
|
||
// Arrange: 随机配置值
|
||
var configValues = new string?[] { null, "", $"Content_{seed.Get}" };
|
||
var agreementValue = configValues[seed.Get % configValues.Length];
|
||
var privacyValue = configValues[(seed.Get + 1) % configValues.Length];
|
||
var aboutValue = configValues[(seed.Get + 2) % configValues.Length];
|
||
var versionValue = configValues[(seed.Get + 3) % configValues.Length];
|
||
|
||
var mockConfigService = new Mock<IConfigService>();
|
||
mockConfigService
|
||
.Setup(x => x.GetConfigValueAsync("user_agreement"))
|
||
.ReturnsAsync(agreementValue);
|
||
mockConfigService
|
||
.Setup(x => x.GetConfigValueAsync("privacy_policy"))
|
||
.ReturnsAsync(privacyValue);
|
||
mockConfigService
|
||
.Setup(x => x.GetConfigValueAsync("about_us"))
|
||
.ReturnsAsync(aboutValue);
|
||
mockConfigService
|
||
.Setup(x => x.GetConfigValueAsync("app_version"))
|
||
.ReturnsAsync(versionValue);
|
||
|
||
var service = new SystemService(mockConfigService.Object, _mockLogger.Object);
|
||
|
||
// Act
|
||
var agreement = service.GetAgreementAsync().GetAwaiter().GetResult();
|
||
var privacy = service.GetPrivacyAsync().GetAwaiter().GetResult();
|
||
var about = service.GetAboutAsync().GetAwaiter().GetResult();
|
||
|
||
// Assert: 所有方法都返回非空 DTO
|
||
return agreement != null && privacy != null && about != null;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Property 8: 所有系统配置方法的响应属性不为 null
|
||
///
|
||
/// **Feature: miniapp-api, Property 8: 响应格式一致性**
|
||
/// **Validates: Requirements 14.1, 14.2, 14.3, 16.1, 16.2, 16.3**
|
||
/// </summary>
|
||
[Property(MaxTest = 100)]
|
||
public bool AllSystemMethods_ResponsePropertiesAreNotNull(PositiveInt seed)
|
||
{
|
||
// Arrange: 随机配置值
|
||
var configValues = new string?[] { null, "", $"Content_{seed.Get}" };
|
||
var agreementValue = configValues[seed.Get % configValues.Length];
|
||
var privacyValue = configValues[(seed.Get + 1) % configValues.Length];
|
||
var aboutValue = configValues[(seed.Get + 2) % configValues.Length];
|
||
var versionValue = configValues[(seed.Get + 3) % configValues.Length];
|
||
|
||
var mockConfigService = new Mock<IConfigService>();
|
||
mockConfigService
|
||
.Setup(x => x.GetConfigValueAsync("user_agreement"))
|
||
.ReturnsAsync(agreementValue);
|
||
mockConfigService
|
||
.Setup(x => x.GetConfigValueAsync("privacy_policy"))
|
||
.ReturnsAsync(privacyValue);
|
||
mockConfigService
|
||
.Setup(x => x.GetConfigValueAsync("about_us"))
|
||
.ReturnsAsync(aboutValue);
|
||
mockConfigService
|
||
.Setup(x => x.GetConfigValueAsync("app_version"))
|
||
.ReturnsAsync(versionValue);
|
||
|
||
var service = new SystemService(mockConfigService.Object, _mockLogger.Object);
|
||
|
||
// Act
|
||
var agreement = service.GetAgreementAsync().GetAwaiter().GetResult();
|
||
var privacy = service.GetPrivacyAsync().GetAwaiter().GetResult();
|
||
var about = service.GetAboutAsync().GetAwaiter().GetResult();
|
||
|
||
// Assert: 所有响应属性都不为 null
|
||
return agreement.Content != null &&
|
||
privacy.Content != null &&
|
||
about.Content != null &&
|
||
about.Version != null;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Property 8: 配置值正确传递到响应中
|
||
///
|
||
/// **Feature: miniapp-api, Property 8: 响应格式一致性**
|
||
/// **Validates: Requirements 14.1, 14.2, 14.3, 16.1, 16.2, 16.3**
|
||
/// </summary>
|
||
[Property(MaxTest = 100)]
|
||
public bool ConfigValues_CorrectlyPassedToResponse(NonEmptyString agreementContent, NonEmptyString privacyContent, NonEmptyString aboutContent, NonEmptyString version)
|
||
{
|
||
// Arrange
|
||
var mockConfigService = new Mock<IConfigService>();
|
||
mockConfigService
|
||
.Setup(x => x.GetConfigValueAsync("user_agreement"))
|
||
.ReturnsAsync(agreementContent.Get);
|
||
mockConfigService
|
||
.Setup(x => x.GetConfigValueAsync("privacy_policy"))
|
||
.ReturnsAsync(privacyContent.Get);
|
||
mockConfigService
|
||
.Setup(x => x.GetConfigValueAsync("about_us"))
|
||
.ReturnsAsync(aboutContent.Get);
|
||
mockConfigService
|
||
.Setup(x => x.GetConfigValueAsync("app_version"))
|
||
.ReturnsAsync(version.Get);
|
||
|
||
var service = new SystemService(mockConfigService.Object, _mockLogger.Object);
|
||
|
||
// Act
|
||
var agreement = service.GetAgreementAsync().GetAwaiter().GetResult();
|
||
var privacy = service.GetPrivacyAsync().GetAwaiter().GetResult();
|
||
var about = service.GetAboutAsync().GetAwaiter().GetResult();
|
||
|
||
// Assert: 配置值正确传递到响应中
|
||
return agreement.Content == agreementContent.Get &&
|
||
privacy.Content == privacyContent.Get &&
|
||
about.Content == aboutContent.Get &&
|
||
about.Version == version.Get;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Property 8: 空配置值时使用默认值或空字符串
|
||
///
|
||
/// **Feature: miniapp-api, Property 8: 响应格式一致性**
|
||
/// **Validates: Requirements 14.1, 14.2, 14.3, 16.1, 16.2, 16.3**
|
||
/// </summary>
|
||
[Fact]
|
||
public void NullConfigValues_UseDefaultOrEmptyString()
|
||
{
|
||
// Arrange
|
||
var mockConfigService = new Mock<IConfigService>();
|
||
mockConfigService
|
||
.Setup(x => x.GetConfigValueAsync(It.IsAny<string>()))
|
||
.ReturnsAsync((string?)null);
|
||
|
||
var service = new SystemService(mockConfigService.Object, _mockLogger.Object);
|
||
|
||
// Act
|
||
var agreement = service.GetAgreementAsync().GetAwaiter().GetResult();
|
||
var privacy = service.GetPrivacyAsync().GetAwaiter().GetResult();
|
||
var about = service.GetAboutAsync().GetAwaiter().GetResult();
|
||
|
||
// Assert
|
||
Assert.Equal(string.Empty, agreement.Content);
|
||
Assert.Equal(string.Empty, privacy.Content);
|
||
Assert.Equal(string.Empty, about.Content);
|
||
Assert.Equal("1.0.0", about.Version); // Version 有默认值
|
||
}
|
||
|
||
#endregion
|
||
}
|