【问题标题】:How to unit test scenarios when token must be expired?令牌必须过期时如何对场景进行单元测试?
【发布时间】:2021-07-09 10:06:40
【问题描述】:

我正在尝试编写单元测试来测试给定令牌过期时的 AuthenticationService 响应。我现在这样做的方式 - 我将到期日期设置为 1 毫秒,但这非常不稳定。有更好的方法吗?

这是我的单元测试方法的代码:

/// <summary>
/// Tests service response when refreshing tokens with non-expired refresh token.
/// </summary>
[Fact]
public async void AuthService_UserRefreshesTokens_AuthenticationResponseWithRefreshTokenHasExpiredError()
{
    // Arrange
    _fixture.JwtCfg.TokenLifetime = new TimeSpan(0, 0, 0, 0, 1);
    _fixture.RefreshTokenCfg.TokenLifetime = new TimeSpan(0, 0, 0, 0, 1);
    var authResponse = await _fixture.TokenSrvc.GenerateTokenPairForUserAsync(_fixture.Users.First());
    var request = new RefreshTokenRequest
    {
        Token = authResponse.Token,
        RefreshToken = authResponse.RefreshToken
    };
    ((List<RefreshToken>)_fixture.RefreshTokens).Add(new RefreshToken { Token = request.RefreshToken });

    // Act
    var response = await _fixture.AuthSrvc.RefreshTokenAsync(request);

    // Assert
    response.Success.Should().BeFalse();
    response.Errors.Should().ContainSingle();
    response.Errors.ToList()[0].Should().Be("Refresh token has expired, user needs to re-login.");
}

使用这种方法,我得到下一个错误:

System.ArgumentException: IDX12401: Expires: 'System.DateTime' must be after NotBefore: 'System.DateTime'.

【问题讨论】:

  • JWT 不会在一毫秒内过期,因为时间戳格式(unix 纪元时间以秒为单位)的分辨率为一秒。因此,您可能会得到 0 或 1 秒,当它为 0 时,您会得到观察到的错误。
  • @jps,感谢您提供的信息,但如何正确测试呢?
  • 在使用令牌或模拟时钟之前等待。
  • 在某些时候,您使用 DateTime.UtcNow 或类似的东西来初始化 Token 并为其生命周期添加 Timespans。当您控制代码中交付的时间时(不直接使用 DateTime,而是可以模拟的接口并可以返回任意日期时间),您可以控制“现在”的内容,并且可以轻松地测试与时间相关的代码。

标签: c# unit-testing asp.net-core token


【解决方案1】:

正如@Ralf 所说,最简单的方法是延迟 1 秒。

/// <summary>
/// Tests service response when refreshing tokens with non-expired refresh token.
/// </summary>
[Fact]
public async void AuthService_UserRefreshesTokens_AuthenticationResponseWithRefreshTokenHasExpiredError()
{
    // Arrange
    _fixture.JwtCfg.TokenLifetime = TimeSpan.FromSeconds(1);
    _fixture.RefreshTokenCfg.TokenLifetime = TimeSpan.FromSeconds(1);
    var authResponse = await _fixture.TokenSrvc.GenerateTokenPairForUserAsync(_fixture.Users.First());
    var request = new RefreshTokenRequest
    {
        Token = authResponse.Token,
        RefreshToken = authResponse.RefreshToken
    };
    ((List<RefreshToken>)_fixture.RefreshTokens).Add(new RefreshToken { Token = request.RefreshToken });

    // now wait a little
    await Task.Delay(1001);

    // Act
    var response = await _fixture.AuthSrvc.RefreshTokenAsync(request);

    // Assert
    response.Success.Should().BeFalse();
    response.Errors.Should().ContainSingle();
    response.Errors.ToList()[0].Should().Be("Refresh token has expired, user needs to re-login.");
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-12
    • 1970-01-01
    • 1970-01-01
    • 2018-12-23
    • 2021-09-21
    相关资源
    最近更新 更多