xiangyixiangqin/server/tests/XiangYi.Api.Tests/AdminApi/AdminBackupControllerIntegrationTests.cs
2026-01-02 18:00:49 +08:00

414 lines
15 KiB
C#
Raw Permalink Blame History

using System.Net;
using System.Net.Http.Json;
using System.Text.Json;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc.Testing;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using NSubstitute;
using Xunit;
using XiangYi.AdminApi;
using XiangYi.Application.DTOs.Requests;
using XiangYi.Application.DTOs.Responses;
using XiangYi.Application.Interfaces;
namespace XiangYi.Api.Tests.AdminApi;
/// <summary>
/// 后台数据备份控制器集成测<E68890>?
/// </summary>
public class AdminBackupControllerIntegrationTests : IClassFixture<WebApplicationFactory<IAdminApiMarker>>
{
private readonly WebApplicationFactory<IAdminApiMarker> _factory;
private readonly IAdminBackupService _mockAdminBackupService;
public AdminBackupControllerIntegrationTests(WebApplicationFactory<IAdminApiMarker> factory)
{
_mockAdminBackupService = Substitute.For<IAdminBackupService>();
_factory = factory.WithWebHostBuilder(builder =>
{
builder.UseEnvironment("Testing");
builder.ConfigureServices(services =>
{
services.RemoveAll<IAdminBackupService>();
services.AddSingleton(_mockAdminBackupService);
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = AdminTestAuthHandler.AuthenticationScheme;
options.DefaultChallengeScheme = AdminTestAuthHandler.AuthenticationScheme;
})
.AddScheme<AuthenticationSchemeOptions, AdminTestAuthHandler>(
AdminTestAuthHandler.AuthenticationScheme, options => { });
});
});
}
/// <summary>
/// 测试获取备份记录列表 - 未授权返<E69D83>?01
/// </summary>
[Fact]
public async Task GetBackupList_WithoutAuth_ReturnsUnauthorized()
{
var client = _factory.CreateClient();
var response = await client.GetAsync("/api/admin/backups");
Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode);
}
/// <summary>
/// 测试获取备份记录列表 - 授权后成<E5908E>?
/// </summary>
[Fact]
public async Task GetBackupList_WithAuth_ReturnsSuccess()
{
var expectedResult = new PagedResult<AdminBackupListDto>
{
Items = new List<AdminBackupListDto>
{
new AdminBackupListDto
{
BackupId = 1,
BackupType = 1,
BackupTypeText = "自动备份",
FileName = "backup_20231231_020000.bak",
FileSize = 1024 * 1024 * 100,
FileSizeText = "100 MB",
Status = 1,
StatusText = "成功",
CreateTime = DateTime.Now.AddHours(-2)
}
},
Total = 1,
PageIndex = 1,
PageSize = 10
};
_mockAdminBackupService.GetBackupListAsync(Arg.Any<AdminBackupQueryRequest>())
.Returns(Task.FromResult(expectedResult));
var client = _factory.CreateClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer admin-token-1");
var response = await client.GetAsync("/api/admin/backups");
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
var content = await response.Content.ReadAsStringAsync();
var result = JsonSerializer.Deserialize<ApiResponse<PagedResult<AdminBackupListDto>>>(content,
new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
Assert.NotNull(result);
Assert.Equal(0, result.Code);
Assert.NotNull(result.Data);
Assert.Single(result.Data.Items);
}
/// <summary>
/// 测试获取备份记录详情 - 成功
/// </summary>
[Fact]
public async Task GetBackupDetail_WithAuth_ReturnsSuccess()
{
var expectedResult = new AdminBackupDetailDto
{
BackupId = 1,
BackupType = 1,
BackupTypeText = "自动备份",
FileName = "backup_20231231_020000.bak",
FileSize = 1024 * 1024 * 100,
FileSizeText = "100 MB",
StorageUrl = "https://cos.example.com/backups/backup_20231231_020000.bak",
Status = 1,
StatusText = "成功",
CreateTime = DateTime.Now.AddHours(-2)
};
_mockAdminBackupService.GetBackupDetailAsync(1)
.Returns(Task.FromResult(expectedResult));
var client = _factory.CreateClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer admin-token-1");
var response = await client.GetAsync("/api/admin/backups/1");
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
var content = await response.Content.ReadAsStringAsync();
var result = JsonSerializer.Deserialize<ApiResponse<AdminBackupDetailDto>>(content,
new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
Assert.NotNull(result);
Assert.Equal(0, result.Code);
Assert.NotNull(result.Data);
Assert.Equal(expectedResult.BackupId, result.Data.BackupId);
}
/// <summary>
/// 测试执行手动备份 - 成功
/// </summary>
[Fact]
public async Task ExecuteManualBackup_WithAuth_ReturnsSuccess()
{
var expectedResult = new AdminBackupDetailDto
{
BackupId = 100,
BackupType = 2,
BackupTypeText = "手动备份",
FileName = "backup_20231231_150000.bak",
FileSize = 1024 * 1024 * 100,
FileSizeText = "100 MB",
StorageUrl = "https://cos.example.com/backups/backup_20231231_150000.bak",
Status = 1,
StatusText = "成功",
AdminId = 1,
CreateTime = DateTime.Now
};
_mockAdminBackupService.ExecuteManualBackupAsync(1)
.Returns(Task.FromResult(expectedResult));
var client = _factory.CreateClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer admin-token-1");
var response = await client.PostAsync("/api/admin/backups", null);
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
var content = await response.Content.ReadAsStringAsync();
var result = JsonSerializer.Deserialize<ApiResponse<AdminBackupDetailDto>>(content,
new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
Assert.NotNull(result);
Assert.Equal(0, result.Code);
Assert.NotNull(result.Data);
Assert.Equal(2, result.Data.BackupType); // 手动备份
}
/// <summary>
/// 测试恢复数据 - 成功
/// </summary>
[Fact]
public async Task RestoreData_WithAuth_ReturnsSuccess()
{
_mockAdminBackupService.RestoreDataAsync(1, 1)
.Returns(Task.FromResult(true));
var client = _factory.CreateClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer admin-token-1");
var response = await client.PostAsync("/api/admin/backups/1/restore", null);
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
var content = await response.Content.ReadAsStringAsync();
var result = JsonSerializer.Deserialize<ApiResponse>(content,
new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
Assert.NotNull(result);
Assert.Equal(0, result.Code);
}
/// <summary>
/// 测试删除备份记录 - 成功
/// </summary>
[Fact]
public async Task DeleteBackup_WithAuth_ReturnsSuccess()
{
_mockAdminBackupService.DeleteBackupAsync(1)
.Returns(Task.FromResult(true));
var client = _factory.CreateClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer admin-token-1");
var response = await client.DeleteAsync("/api/admin/backups/1");
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
var content = await response.Content.ReadAsStringAsync();
var result = JsonSerializer.Deserialize<ApiResponse>(content,
new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
Assert.NotNull(result);
Assert.Equal(0, result.Code);
}
/// <summary>
/// 测试获取备份统计信息 - 成功
/// </summary>
[Fact]
public async Task GetBackupStatistics_WithAuth_ReturnsSuccess()
{
var expectedResult = new AdminBackupStatisticsDto
{
TotalCount = 100,
SuccessCount = 98,
FailedCount = 2,
AutoCount = 90,
ManualCount = 10,
TotalSize = 1024L * 1024 * 1024 * 10, // 10 GB
TotalSizeText = "10 GB",
LastBackupTime = DateTime.Now.AddHours(-2),
LastSuccessBackupTime = DateTime.Now.AddHours(-2)
};
_mockAdminBackupService.GetBackupStatisticsAsync()
.Returns(Task.FromResult(expectedResult));
var client = _factory.CreateClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer admin-token-1");
var response = await client.GetAsync("/api/admin/backups/statistics");
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
var content = await response.Content.ReadAsStringAsync();
var result = JsonSerializer.Deserialize<ApiResponse<AdminBackupStatisticsDto>>(content,
new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
Assert.NotNull(result);
Assert.Equal(0, result.Code);
Assert.NotNull(result.Data);
Assert.Equal(expectedResult.TotalCount, result.Data.TotalCount);
Assert.Equal(expectedResult.SuccessCount, result.Data.SuccessCount);
}
/// <summary>
/// 测试清理过期备份 - 成功
/// </summary>
[Fact]
public async Task CleanupExpiredBackups_WithAuth_ReturnsSuccess()
{
_mockAdminBackupService.CleanupExpiredBackupsAsync()
.Returns(Task.FromResult(5));
var client = _factory.CreateClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer admin-token-1");
var response = await client.PostAsync("/api/admin/backups/cleanup", null);
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
var content = await response.Content.ReadAsStringAsync();
var result = JsonSerializer.Deserialize<ApiResponse<int>>(content,
new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
Assert.NotNull(result);
Assert.Equal(0, result.Code);
Assert.Equal(5, result.Data);
}
/// <summary>
/// 测试备份流程 - 手动备份并恢<E5B9B6>?
/// </summary>
[Fact]
public async Task BackupFlow_ManualBackupAndRestore_Success()
{
var backupId = 100L;
var backupResult = new AdminBackupDetailDto
{
BackupId = backupId,
BackupType = 2,
BackupTypeText = "手动备份",
FileName = "backup_20231231_150000.bak",
FileSize = 1024 * 1024 * 100,
Status = 1,
StatusText = "成功"
};
_mockAdminBackupService.ExecuteManualBackupAsync(1)
.Returns(Task.FromResult(backupResult));
_mockAdminBackupService.GetBackupDetailAsync(backupId)
.Returns(Task.FromResult(backupResult));
_mockAdminBackupService.RestoreDataAsync(backupId, 1)
.Returns(Task.FromResult(true));
var client = _factory.CreateClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer admin-token-1");
// Execute manual backup
var backupResponse = await client.PostAsync("/api/admin/backups", null);
Assert.Equal(HttpStatusCode.OK, backupResponse.StatusCode);
// Get backup detail
var detailResponse = await client.GetAsync($"/api/admin/backups/{backupId}");
Assert.Equal(HttpStatusCode.OK, detailResponse.StatusCode);
// Restore data
var restoreResponse = await client.PostAsync($"/api/admin/backups/{backupId}/restore", null);
Assert.Equal(HttpStatusCode.OK, restoreResponse.StatusCode);
}
/// <summary>
/// 测试恢复数据失败 - 返回错误
/// </summary>
[Fact]
public async Task RestoreData_WhenFails_ReturnsError()
{
_mockAdminBackupService.RestoreDataAsync(1, 1)
.Returns(Task.FromResult(false));
var client = _factory.CreateClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer admin-token-1");
var response = await client.PostAsync("/api/admin/backups/1/restore", null);
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
var content = await response.Content.ReadAsStringAsync();
var result = JsonSerializer.Deserialize<ApiResponse>(content,
new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
Assert.NotNull(result);
Assert.Equal(40001, result.Code);
}
/// <summary>
/// 测试备份列表按类型筛<E59E8B>?- 成功
/// </summary>
[Fact]
public async Task GetBackupList_WithTypeFilter_ReturnsFilteredResults()
{
var expectedResult = new PagedResult<AdminBackupListDto>
{
Items = new List<AdminBackupListDto>
{
new AdminBackupListDto
{
BackupId = 1,
BackupType = 2,
BackupTypeText = "手动备份",
Status = 1
}
},
Total = 1,
PageIndex = 1,
PageSize = 10
};
_mockAdminBackupService.GetBackupListAsync(Arg.Is<AdminBackupQueryRequest>(r => r.BackupType == 2))
.Returns(Task.FromResult(expectedResult));
var client = _factory.CreateClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer admin-token-1");
var response = await client.GetAsync("/api/admin/backups?backupType=2");
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
var content = await response.Content.ReadAsStringAsync();
var result = JsonSerializer.Deserialize<ApiResponse<PagedResult<AdminBackupListDto>>>(content,
new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
Assert.NotNull(result);
Assert.Equal(0, result.Code);
Assert.NotNull(result.Data);
Assert.All(result.Data.Items, item => Assert.Equal(2, item.BackupType));
}
}