build-flow.api/tests/BuildFlow.Platform.Tests/Auth/RefreshTokenCommandHandlerTests.cs
xiangning f550074fcc test(platform): 添加平台模块测试基础设施和RAG端到端测试
- 为平台测试添加EntityFrameworkCore和Xunit引用
- 实现PlatformTestDb创建带审计字段自动填充的测试数据库
- 添加DictionaryConfiguration支持配置值获取测试
- 实现完整的密码强度验证规则
- 添加RAG问答全链路端到端测试
- 创建多个Stub服务用于解耦外部依赖测试
- 实现测试专用的当前用户上下文
2026-07-07 17:31:50 +08:00

85 lines
3.1 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using FluentAssertions;
using Microsoft.EntityFrameworkCore;
using Xunit;
using BuildFlow.Platform.Application.Auth.Commands;
using BuildFlow.Platform.Application.Auth.Handlers;
using BuildFlow.Shared.Domain.Exceptions;
namespace BuildFlow.Platform.Tests.Auth;
/// <summary>
/// 刷新令牌 Command 处理器单元测试。覆盖正常刷新 + Rotation、过期/吊销、不存在等路径。
/// </summary>
public class RefreshTokenCommandHandlerTests
{
private static async Task<(Platform.Infrastructure.Persistence.PlatformDbContext db, string refreshToken)> SeedTokenAsync(
bool revoked = false, DateTime? expiresAt = null, int permissionVersion = 0)
{
var db = PlatformTestDb.CreateDbContext();
var userId = Guid.NewGuid();
await PlatformTestDb.SeedUserAsync(db, userId, "refresher", permissionVersion: permissionVersion);
var token = "valid-refresh-token";
db.RefreshTokens.Add(new BuildFlow.Platform.Domain.Entities.RefreshToken
{
Id = Guid.NewGuid(),
UserId = userId,
Token = token,
ExpiresAt = expiresAt ?? DateTime.UtcNow.AddDays(1),
IsRevoked = revoked,
CreatedBy = "test",
CreatedAt = DateTime.UtcNow,
UpdatedBy = "test",
UpdatedAt = DateTime.UtcNow,
});
await db.SaveChangesAsync();
return (db, token);
}
[Fact]
public async Task Handle_ValidToken_ShouldRotateAndIssueNewToken()
{
// Arrange
var (db, token) = await SeedTokenAsync();
var handler = new RefreshTokenCommandHandler(db, PlatformTestDb.CreateConfig());
// Act
var result = await handler.Handle(new RefreshTokenCommand(token), CancellationToken.None);
// Assert:新 token 签发 + 旧 token 被吊销(Rotation)
result.AccessToken.Should().NotBeNullOrWhiteSpace();
result.RefreshToken.Should().NotBe(token);
var oldToken = await db.RefreshTokens.FirstAsync(rt => rt.Token == token);
oldToken.IsRevoked.Should().BeTrue();
}
[Fact]
public async Task Handle_RevokedToken_ShouldThrowExpired()
{
// Arrange
var (db, token) = await SeedTokenAsync(revoked: true);
var handler = new RefreshTokenCommandHandler(db, PlatformTestDb.CreateConfig());
// Act
var act = () => handler.Handle(new RefreshTokenCommand(token), CancellationToken.None);
// Assert
await act.Should().ThrowAsync<UnauthorizedException>()
.WithMessage("*刷新令牌已过期或已吊销*");
}
[Fact]
public async Task Handle_NonExistentToken_ShouldThrowUnauthorized()
{
// Arrange
var db = PlatformTestDb.CreateDbContext();
var handler = new RefreshTokenCommandHandler(db, PlatformTestDb.CreateConfig());
// Act
var act = () => handler.Handle(new RefreshTokenCommand("nonexistent"), CancellationToken.None);
// Assert
await act.Should().ThrowAsync<UnauthorizedException>()
.WithMessage("*无效的刷新令牌*");
}
}