build-flow.api/tests/BuildFlow.Platform.Tests/Auth/RefreshTokenCommandHandlerTests.cs
xiangning 51eea796e2 refactor(rag): 重构AI模型相关代码结构和数据库迁移逻辑
- 将AI模型相关端点、命令、处理器移动到模块内部统一管理
- 优化数据库迁移脚本,添加对不同环境表状态的兼容处理逻辑
- 为异常处理添加错误码枚举参数,统一错误处理方式
- 重构多处业务逻辑中的异常抛出方式,增强代码一致性
- 移除独立的组件清单分组和项目定义,简化前端物料面板数据结构
- 修复测试代码中实体引用路径错误问题
- 添加新的监控模块测试项目到解决方案文件中
2026-07-20 08:25:18 +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.RefreshTokenEntity
{
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("*无效的刷新令牌*");
}
}