464 lines
16 KiB
C#
464 lines
16 KiB
C#
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>
|
|
/// 后台敏感词管理控制器集成测试
|
|
/// </summary>
|
|
public class AdminSensitiveWordControllerIntegrationTests : IClassFixture<WebApplicationFactory<IAdminApiMarker>>
|
|
{
|
|
private readonly WebApplicationFactory<IAdminApiMarker> _factory;
|
|
private readonly IAdminSensitiveWordService _mockAdminSensitiveWordService;
|
|
|
|
public AdminSensitiveWordControllerIntegrationTests(WebApplicationFactory<IAdminApiMarker> factory)
|
|
{
|
|
_mockAdminSensitiveWordService = Substitute.For<IAdminSensitiveWordService>();
|
|
|
|
_factory = factory.WithWebHostBuilder(builder =>
|
|
{
|
|
builder.UseEnvironment("Testing");
|
|
builder.ConfigureServices(services =>
|
|
{
|
|
services.RemoveAll<IAdminSensitiveWordService>();
|
|
services.AddSingleton(_mockAdminSensitiveWordService);
|
|
|
|
services.AddAuthentication(options =>
|
|
{
|
|
options.DefaultAuthenticateScheme = AdminTestAuthHandler.AuthenticationScheme;
|
|
options.DefaultChallengeScheme = AdminTestAuthHandler.AuthenticationScheme;
|
|
})
|
|
.AddScheme<AuthenticationSchemeOptions, AdminTestAuthHandler>(
|
|
AdminTestAuthHandler.AuthenticationScheme, options => { });
|
|
});
|
|
});
|
|
}
|
|
|
|
/// <summary>
|
|
/// 测试获取敏感词列表 - 未授权返回401
|
|
/// </summary>
|
|
[Fact]
|
|
public async Task GetSensitiveWordList_WithoutAuth_ReturnsUnauthorized()
|
|
{
|
|
var client = _factory.CreateClient();
|
|
var response = await client.GetAsync("/api/admin/sensitiveWords");
|
|
Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode);
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// 测试获取敏感词列表 - 授权后成功
|
|
/// </summary>
|
|
[Fact]
|
|
public async Task GetSensitiveWordList_WithAuth_ReturnsSuccess()
|
|
{
|
|
var expectedResult = new PagedResult<AdminSensitiveWordDto>
|
|
{
|
|
Items = new List<AdminSensitiveWordDto>
|
|
{
|
|
new AdminSensitiveWordDto
|
|
{
|
|
Id = 1,
|
|
Word = "敏感词1",
|
|
Category = "广告",
|
|
Level = 1,
|
|
LevelName = "替换",
|
|
Status = 1,
|
|
StatusName = "启用"
|
|
}
|
|
},
|
|
Total = 1,
|
|
PageIndex = 1,
|
|
PageSize = 10
|
|
};
|
|
|
|
_mockAdminSensitiveWordService.GetSensitiveWordListAsync(Arg.Any<AdminSensitiveWordQueryRequest>())
|
|
.Returns(Task.FromResult(expectedResult));
|
|
|
|
var client = _factory.CreateClient();
|
|
client.DefaultRequestHeaders.Add("Authorization", "Bearer admin-token-1");
|
|
|
|
var response = await client.GetAsync("/api/admin/sensitiveWords");
|
|
|
|
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
|
|
|
var content = await response.Content.ReadAsStringAsync();
|
|
var result = JsonSerializer.Deserialize<ApiResponse<PagedResult<AdminSensitiveWordDto>>>(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 GetSensitiveWordDetail_WithAuth_ReturnsSuccess()
|
|
{
|
|
var expectedResult = new AdminSensitiveWordDto
|
|
{
|
|
Id = 1,
|
|
Word = "敏感词1",
|
|
Category = "广告",
|
|
Level = 1,
|
|
LevelName = "替换",
|
|
Status = 1,
|
|
StatusName = "启用"
|
|
};
|
|
|
|
_mockAdminSensitiveWordService.GetSensitiveWordByIdAsync(1)
|
|
.Returns(Task.FromResult(expectedResult));
|
|
|
|
var client = _factory.CreateClient();
|
|
client.DefaultRequestHeaders.Add("Authorization", "Bearer admin-token-1");
|
|
|
|
var response = await client.GetAsync("/api/admin/sensitiveWords/1");
|
|
|
|
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
|
|
|
var content = await response.Content.ReadAsStringAsync();
|
|
var result = JsonSerializer.Deserialize<ApiResponse<AdminSensitiveWordDto>>(content,
|
|
new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
|
|
|
|
Assert.NotNull(result);
|
|
Assert.Equal(0, result.Code);
|
|
Assert.NotNull(result.Data);
|
|
Assert.Equal(expectedResult.Id, result.Data.Id);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 测试创建敏感词 - 成功
|
|
/// </summary>
|
|
[Fact]
|
|
public async Task CreateSensitiveWord_WithAuth_ReturnsSuccess()
|
|
{
|
|
_mockAdminSensitiveWordService.CreateSensitiveWordAsync(Arg.Any<CreateSensitiveWordRequest>(), 1)
|
|
.Returns(Task.FromResult(100L));
|
|
|
|
var client = _factory.CreateClient();
|
|
client.DefaultRequestHeaders.Add("Authorization", "Bearer admin-token-1");
|
|
|
|
var request = new CreateSensitiveWordRequest
|
|
{
|
|
Word = "新敏感词",
|
|
Category = "广告",
|
|
Level = 1,
|
|
Status = 1
|
|
};
|
|
|
|
var response = await client.PostAsJsonAsync("/api/admin/sensitiveWords", request);
|
|
|
|
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
|
|
|
var content = await response.Content.ReadAsStringAsync();
|
|
var result = JsonSerializer.Deserialize<ApiResponse<long>>(content,
|
|
new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
|
|
|
|
Assert.NotNull(result);
|
|
Assert.Equal(0, result.Code);
|
|
Assert.Equal(100L, result.Data);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 测试更新敏感词 - 成功
|
|
/// </summary>
|
|
[Fact]
|
|
public async Task UpdateSensitiveWord_WithAuth_ReturnsSuccess()
|
|
{
|
|
_mockAdminSensitiveWordService.UpdateSensitiveWordAsync(1, Arg.Any<UpdateSensitiveWordRequest>(), 1)
|
|
.Returns(Task.FromResult(true));
|
|
|
|
var client = _factory.CreateClient();
|
|
client.DefaultRequestHeaders.Add("Authorization", "Bearer admin-token-1");
|
|
|
|
var request = new UpdateSensitiveWordRequest
|
|
{
|
|
Word = "更新后的敏感词",
|
|
Category = "广告",
|
|
Level = 2,
|
|
Status = 1
|
|
};
|
|
|
|
var response = await client.PutAsJsonAsync("/api/admin/sensitiveWords/1", request);
|
|
|
|
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 DeleteSensitiveWord_WithAuth_ReturnsSuccess()
|
|
{
|
|
_mockAdminSensitiveWordService.DeleteSensitiveWordAsync(1, 1)
|
|
.Returns(Task.FromResult(true));
|
|
|
|
var client = _factory.CreateClient();
|
|
client.DefaultRequestHeaders.Add("Authorization", "Bearer admin-token-1");
|
|
|
|
var response = await client.DeleteAsync("/api/admin/sensitiveWords/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 BatchDeleteSensitiveWords_WithAuth_ReturnsSuccess()
|
|
{
|
|
_mockAdminSensitiveWordService.BatchDeleteSensitiveWordsAsync(Arg.Any<List<long>>(), 1)
|
|
.Returns(Task.FromResult(3));
|
|
|
|
var client = _factory.CreateClient();
|
|
client.DefaultRequestHeaders.Add("Authorization", "Bearer admin-token-1");
|
|
|
|
var request = new BatchDeleteSensitiveWordRequest
|
|
{
|
|
Ids = new List<long> { 1, 2, 3 }
|
|
};
|
|
|
|
var response = await client.PostAsJsonAsync("/api/admin/sensitiveWords/batchDelete", request);
|
|
|
|
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(3, result.Data);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 测试批量导入敏感词 - 成功
|
|
/// </summary>
|
|
[Fact]
|
|
public async Task ImportSensitiveWords_WithAuth_ReturnsSuccess()
|
|
{
|
|
var expectedResult = new ImportSensitiveWordResult
|
|
{
|
|
TotalCount = 10,
|
|
SuccessCount = 8,
|
|
SkippedCount = 2,
|
|
UpdatedCount = 0,
|
|
FailedCount = 0
|
|
};
|
|
|
|
_mockAdminSensitiveWordService.ImportSensitiveWordsAsync(Arg.Any<ImportSensitiveWordRequest>(), 1)
|
|
.Returns(Task.FromResult(expectedResult));
|
|
|
|
var client = _factory.CreateClient();
|
|
client.DefaultRequestHeaders.Add("Authorization", "Bearer admin-token-1");
|
|
|
|
var request = new ImportSensitiveWordRequest
|
|
{
|
|
Words = new List<string> { "敏感词1", "敏感词2", "敏感词3" },
|
|
Category = "广告",
|
|
Level = 1,
|
|
OverwriteExisting = false
|
|
};
|
|
|
|
var response = await client.PostAsJsonAsync("/api/admin/sensitiveWords/import", request);
|
|
|
|
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
|
|
|
var content = await response.Content.ReadAsStringAsync();
|
|
var result = JsonSerializer.Deserialize<ApiResponse<ImportSensitiveWordResult>>(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 UpdateSensitiveWordStatus_WithAuth_ReturnsSuccess()
|
|
{
|
|
_mockAdminSensitiveWordService.UpdateSensitiveWordStatusAsync(1, 2, 1)
|
|
.Returns(Task.FromResult(true));
|
|
|
|
var client = _factory.CreateClient();
|
|
client.DefaultRequestHeaders.Add("Authorization", "Bearer admin-token-1");
|
|
|
|
var response = await client.PutAsync("/api/admin/sensitiveWords/1/status/2", 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 GetCategories_WithAuth_ReturnsSuccess()
|
|
{
|
|
var expectedResult = new List<string> { "政治", "色情", "广告", "其他" };
|
|
|
|
_mockAdminSensitiveWordService.GetCategoriesAsync()
|
|
.Returns(Task.FromResult(expectedResult));
|
|
|
|
var client = _factory.CreateClient();
|
|
client.DefaultRequestHeaders.Add("Authorization", "Bearer admin-token-1");
|
|
|
|
var response = await client.GetAsync("/api/admin/sensitiveWords/categories");
|
|
|
|
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
|
|
|
var content = await response.Content.ReadAsStringAsync();
|
|
var result = JsonSerializer.Deserialize<ApiResponse<List<string>>>(content,
|
|
new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
|
|
|
|
Assert.NotNull(result);
|
|
Assert.Equal(0, result.Code);
|
|
Assert.NotNull(result.Data);
|
|
Assert.Equal(4, result.Data.Count);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 测试敏感词CRUD流程 - 完整流程测试
|
|
/// </summary>
|
|
[Fact]
|
|
public async Task SensitiveWordCRUD_CompleteFlow_Success()
|
|
{
|
|
var wordId = 100L;
|
|
|
|
_mockAdminSensitiveWordService.CreateSensitiveWordAsync(Arg.Any<CreateSensitiveWordRequest>(), 1)
|
|
.Returns(Task.FromResult(wordId));
|
|
|
|
_mockAdminSensitiveWordService.GetSensitiveWordByIdAsync(wordId)
|
|
.Returns(Task.FromResult(new AdminSensitiveWordDto
|
|
{
|
|
Id = wordId,
|
|
Word = "测试敏感词",
|
|
Category = "广告",
|
|
Level = 1,
|
|
Status = 1
|
|
}));
|
|
|
|
_mockAdminSensitiveWordService.UpdateSensitiveWordAsync(wordId, Arg.Any<UpdateSensitiveWordRequest>(), 1)
|
|
.Returns(Task.FromResult(true));
|
|
|
|
_mockAdminSensitiveWordService.DeleteSensitiveWordAsync(wordId, 1)
|
|
.Returns(Task.FromResult(true));
|
|
|
|
var client = _factory.CreateClient();
|
|
client.DefaultRequestHeaders.Add("Authorization", "Bearer admin-token-1");
|
|
|
|
// Create
|
|
var createRequest = new CreateSensitiveWordRequest
|
|
{
|
|
Word = "测试敏感词",
|
|
Category = "广告",
|
|
Level = 1,
|
|
Status = 1
|
|
};
|
|
var createResponse = await client.PostAsJsonAsync("/api/admin/sensitiveWords", createRequest);
|
|
Assert.Equal(HttpStatusCode.OK, createResponse.StatusCode);
|
|
|
|
// Read
|
|
var readResponse = await client.GetAsync($"/api/admin/sensitiveWords/{wordId}");
|
|
Assert.Equal(HttpStatusCode.OK, readResponse.StatusCode);
|
|
|
|
// Update
|
|
var updateRequest = new UpdateSensitiveWordRequest
|
|
{
|
|
Word = "更新后的敏感词",
|
|
Category = "广告",
|
|
Level = 2,
|
|
Status = 1
|
|
};
|
|
var updateResponse = await client.PutAsJsonAsync($"/api/admin/sensitiveWords/{wordId}", updateRequest);
|
|
Assert.Equal(HttpStatusCode.OK, updateResponse.StatusCode);
|
|
|
|
// Delete
|
|
var deleteResponse = await client.DeleteAsync($"/api/admin/sensitiveWords/{wordId}");
|
|
Assert.Equal(HttpStatusCode.OK, deleteResponse.StatusCode);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 测试敏感词列表按分类筛选 - 成功
|
|
/// </summary>
|
|
[Fact]
|
|
public async Task GetSensitiveWordList_WithCategoryFilter_ReturnsFilteredResults()
|
|
{
|
|
var expectedResult = new PagedResult<AdminSensitiveWordDto>
|
|
{
|
|
Items = new List<AdminSensitiveWordDto>
|
|
{
|
|
new AdminSensitiveWordDto
|
|
{
|
|
Id = 1,
|
|
Word = "广告词",
|
|
Category = "广告",
|
|
Level = 1,
|
|
Status = 1
|
|
}
|
|
},
|
|
Total = 1,
|
|
PageIndex = 1,
|
|
PageSize = 10
|
|
};
|
|
|
|
_mockAdminSensitiveWordService.GetSensitiveWordListAsync(Arg.Is<AdminSensitiveWordQueryRequest>(r => r.Category == "广告"))
|
|
.Returns(Task.FromResult(expectedResult));
|
|
|
|
var client = _factory.CreateClient();
|
|
client.DefaultRequestHeaders.Add("Authorization", "Bearer admin-token-1");
|
|
|
|
var response = await client.GetAsync("/api/admin/sensitiveWords?category=广告");
|
|
|
|
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
|
|
|
var content = await response.Content.ReadAsStringAsync();
|
|
var result = JsonSerializer.Deserialize<ApiResponse<PagedResult<AdminSensitiveWordDto>>>(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("广告", item.Category));
|
|
}
|
|
}
|