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; /// /// 后台资料审核控制器集成测试 /// public class AdminProfileAuditControllerIntegrationTests : IClassFixture> { private readonly WebApplicationFactory _factory; private readonly IAdminProfileAuditService _mockAdminProfileAuditService; public AdminProfileAuditControllerIntegrationTests(WebApplicationFactory factory) { _mockAdminProfileAuditService = Substitute.For(); _factory = factory.WithWebHostBuilder(builder => { builder.UseEnvironment("Testing"); builder.ConfigureServices(services => { services.RemoveAll(); services.AddSingleton(_mockAdminProfileAuditService); services.AddAuthentication(options => { options.DefaultAuthenticateScheme = AdminTestAuthHandler.AuthenticationScheme; options.DefaultChallengeScheme = AdminTestAuthHandler.AuthenticationScheme; }) .AddScheme( AdminTestAuthHandler.AuthenticationScheme, options => { }); }); }); } /// /// 测试获取待审核资料列表 - 未授权返回401 /// [Fact] public async Task GetPendingProfiles_WithoutAuth_ReturnsUnauthorized() { var client = _factory.CreateClient(); var response = await client.GetAsync("/api/admin/profiles/pending"); Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode); } /// /// 测试获取待审核资料列表 - 授权后成功 /// [Fact] public async Task GetPendingProfiles_WithAuth_ReturnsSuccess() { var expectedResult = new PagedResult { Items = new List { new AdminPendingProfileDto { ProfileId = 1, UserId = 100, XiangQinNo = "123456", Nickname = "李家长(父亲)", Relationship = 1, RelationshipText = "父亲", Surname = "李", ChildGender = 1, ChildGenderText = "男", Age = 28, WorkCity = "北京", AuditStatus = 0, AuditStatusText = "待审核", SubmitTime = DateTime.Now.AddHours(-2), PhotoCount = 3 } }, Total = 1, PageIndex = 1, PageSize = 20 }; _mockAdminProfileAuditService.GetPendingProfilesAsync(Arg.Any()) .Returns(Task.FromResult(expectedResult)); var client = _factory.CreateClient(); client.DefaultRequestHeaders.Add("Authorization", "Bearer admin-token-1"); var response = await client.GetAsync("/api/admin/profiles/pending"); Assert.Equal(HttpStatusCode.OK, response.StatusCode); var content = await response.Content.ReadAsStringAsync(); var result = JsonSerializer.Deserialize>>(content, new JsonSerializerOptions { PropertyNameCaseInsensitive = true }); Assert.NotNull(result); Assert.Equal(0, result.Code); Assert.NotNull(result.Data); Assert.Single(result.Data.Items); Assert.Equal("待审核", result.Data.Items[0].AuditStatusText); } /// /// 测试获取资料审核详情 - 成功 /// [Fact] public async Task GetProfileDetail_WithAuth_ReturnsSuccess() { var expectedResult = new AdminProfileAuditDetailDto { ProfileId = 1, UserId = 100, XiangQinNo = "123456", Nickname = "李家长(父亲)", Relationship = 1, RelationshipText = "父亲", Surname = "李", ChildGender = 1, ChildGenderText = "男", BirthYear = 1996, Age = 28, Education = 4, EducationText = "本科", WorkProvince = "北京", WorkCity = "北京", Occupation = "软件工程师", MonthlyIncome = 4, MonthlyIncomeText = "2-3万", Height = 175, Weight = 70, HouseStatus = 1, HouseStatusText = "有房", CarStatus = 1, CarStatusText = "有车", MarriageStatus = 1, MarriageStatusText = "未婚", ExpectMarryTime = 2, ExpectMarryTimeText = "1-2年内", Introduction = "这是一段自我介绍", IsPhotoPublic = true, WeChatNo = "wx123456", AuditStatus = 0, AuditStatusText = "待审核", Photos = new List { new AdminUserPhotoDto { PhotoId = 1, PhotoUrl = "https://example.com/photo1.jpg", Sort = 1 } } }; _mockAdminProfileAuditService.GetProfileDetailAsync(1) .Returns(Task.FromResult(expectedResult)); var client = _factory.CreateClient(); client.DefaultRequestHeaders.Add("Authorization", "Bearer admin-token-1"); var response = await client.GetAsync("/api/admin/profiles/1"); Assert.Equal(HttpStatusCode.OK, response.StatusCode); var content = await response.Content.ReadAsStringAsync(); var result = JsonSerializer.Deserialize>(content, new JsonSerializerOptions { PropertyNameCaseInsensitive = true }); Assert.NotNull(result); Assert.Equal(0, result.Code); Assert.NotNull(result.Data); Assert.Equal(expectedResult.ProfileId, result.Data.ProfileId); Assert.NotNull(result.Data.Photos); Assert.Single(result.Data.Photos); } /// /// 测试审核通过资料 - 成功 /// [Fact] public async Task ApproveProfile_WithAuth_ReturnsSuccess() { _mockAdminProfileAuditService.ApproveProfileAsync(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/profiles/1/approve", null); Assert.Equal(HttpStatusCode.OK, response.StatusCode); var content = await response.Content.ReadAsStringAsync(); var result = JsonSerializer.Deserialize(content, new JsonSerializerOptions { PropertyNameCaseInsensitive = true }); Assert.NotNull(result); Assert.Equal(0, result.Code); } /// /// 测试审核拒绝资料 - 成功 /// [Fact] public async Task RejectProfile_WithAuth_ReturnsSuccess() { _mockAdminProfileAuditService.RejectProfileAsync(1, 1, "资料不完整") .Returns(Task.FromResult(true)); var client = _factory.CreateClient(); client.DefaultRequestHeaders.Add("Authorization", "Bearer admin-token-1"); var request = new RejectProfileRequest { RejectReason = "资料不完整" }; var response = await client.PostAsJsonAsync("/api/admin/profiles/1/reject", request); Assert.Equal(HttpStatusCode.OK, response.StatusCode); var content = await response.Content.ReadAsStringAsync(); var result = JsonSerializer.Deserialize(content, new JsonSerializerOptions { PropertyNameCaseInsensitive = true }); Assert.NotNull(result); Assert.Equal(0, result.Code); } /// /// 测试审核通过失败 - 返回错误 /// [Fact] public async Task ApproveProfile_WhenFails_ReturnsError() { _mockAdminProfileAuditService.ApproveProfileAsync(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/profiles/1/approve", null); Assert.Equal(HttpStatusCode.OK, response.StatusCode); var content = await response.Content.ReadAsStringAsync(); var result = JsonSerializer.Deserialize(content, new JsonSerializerOptions { PropertyNameCaseInsensitive = true }); Assert.NotNull(result); Assert.Equal(40001, result.Code); } /// /// 测试资料审核完整流程 - 从待审核到通过 /// [Fact] public async Task ProfileAuditFlow_FromPendingToApproved_Success() { // 设置待审核资料 var pendingProfile = new AdminProfileAuditDetailDto { ProfileId = 1, AuditStatus = 0, AuditStatusText = "待审核" }; _mockAdminProfileAuditService.GetProfileDetailAsync(1) .Returns(Task.FromResult(pendingProfile)); _mockAdminProfileAuditService.ApproveProfileAsync(1, 1) .Returns(Task.FromResult(true)); var client = _factory.CreateClient(); client.DefaultRequestHeaders.Add("Authorization", "Bearer admin-token-1"); // 获取资料详情 var detailResponse = await client.GetAsync("/api/admin/profiles/1"); Assert.Equal(HttpStatusCode.OK, detailResponse.StatusCode); // 审核通过 var approveResponse = await client.PostAsync("/api/admin/profiles/1/approve", null); Assert.Equal(HttpStatusCode.OK, approveResponse.StatusCode); var content = await approveResponse.Content.ReadAsStringAsync(); var result = JsonSerializer.Deserialize(content, new JsonSerializerOptions { PropertyNameCaseInsensitive = true }); Assert.NotNull(result); Assert.Equal(0, result.Code); } }