171 lines
5.4 KiB
C#
171 lines
5.4 KiB
C#
using System.IdentityModel.Tokens.Jwt;
|
|
using Application.Services;
|
|
using Domain.Entities;
|
|
using Domain.Interface;
|
|
using Microsoft.Extensions.Configuration;
|
|
using NSubstitute;
|
|
|
|
namespace Application.UnitTest.Services;
|
|
|
|
public class JwtServiceTests
|
|
{
|
|
private readonly IConfiguration _configuration = Substitute.For<IConfiguration>();
|
|
private readonly IUserRepository _userRepository = Substitute.For<IUserRepository>();
|
|
private readonly IUnitOfWork _unitOfWork = Substitute.For<IUnitOfWork>();
|
|
private readonly JwtService _sut;
|
|
|
|
public JwtServiceTests()
|
|
{
|
|
var section = Substitute.For<IConfigurationSection>();
|
|
section.Value.Returns("veryveryveryveryveryveryverysecretkey");
|
|
_configuration.GetSection("Jwt:Key").Returns(section);
|
|
|
|
_configuration["Jwt:Key"].Returns("veryveryveryveryveryveryverysecretkey");
|
|
_configuration["Jwt:Issuer"].Returns("https://localhost:7091");
|
|
_configuration["Jwt:Audience"].Returns("http://localhost:5184");
|
|
|
|
_sut = new JwtService(_configuration, _userRepository, _unitOfWork);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task GenerateTokenAsync_ShouldReturnToken_WhenUserIsValid()
|
|
{
|
|
var user = new User
|
|
{
|
|
Id = 1,
|
|
Username = "testuser",
|
|
Email = "test@example.com",
|
|
Password = "hash"
|
|
};
|
|
_userRepository.GetUserRolesByEmailAsync(user.Email)
|
|
.Returns(["User"]);
|
|
|
|
var token = await _sut.GenerateTokenAsync(user);
|
|
|
|
Assert.NotNull(token);
|
|
Assert.NotEmpty(token);
|
|
|
|
var handler = new JwtSecurityTokenHandler();
|
|
var jwtToken = handler.ReadJwtToken(token);
|
|
|
|
Assert.Equal("https://localhost:7091", jwtToken.Issuer);
|
|
Assert.Contains(jwtToken.Claims, c => c.Type == "email" && c.Value == user.Email);
|
|
Assert.Contains(jwtToken.Claims, c => c.Type == "UserId" && c.Value == "1");
|
|
Assert.Contains(jwtToken.Claims, c => c.Type == "username" && c.Value == user.Username);
|
|
Assert.Contains(jwtToken.Claims, c => c.Type == "role" && c.Value == "User");
|
|
}
|
|
|
|
[Fact]
|
|
public async Task GenerateTokenAsync_ShouldIncludeAllRoles()
|
|
{
|
|
var user = new User
|
|
{
|
|
Id = 2,
|
|
Username = "adminuser",
|
|
Email = "admin@example.com",
|
|
Password = "hash"
|
|
};
|
|
_userRepository.GetUserRolesByEmailAsync(user.Email)
|
|
.Returns(["Admin", "User"]);
|
|
|
|
var token = await _sut.GenerateTokenAsync(user);
|
|
|
|
var handler = new JwtSecurityTokenHandler();
|
|
var jwtToken = handler.ReadJwtToken(token);
|
|
var roleClaims = jwtToken.Claims.Where(c => c.Type == "role").Select(c => c.Value).ToList();
|
|
|
|
Assert.Contains("Admin", roleClaims);
|
|
Assert.Contains("User", roleClaims);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task GenerateAndSaveRefreshTokenAsync_ShouldUpdateUserAndCommit()
|
|
{
|
|
var user = new User
|
|
{
|
|
Id = 1,
|
|
Username = "testuser",
|
|
Email = "test@example.com",
|
|
Password = "hash"
|
|
};
|
|
|
|
var refreshToken = await _sut.GenerateAndSaveRefreshTokenAsync(user);
|
|
|
|
Assert.NotNull(refreshToken);
|
|
Assert.NotEmpty(refreshToken);
|
|
Assert.Equal(refreshToken, user.RefreshToken);
|
|
Assert.NotNull(user.RefreshTokenExpiryTime);
|
|
Assert.True(user.RefreshTokenExpiryTime > DateTime.UtcNow);
|
|
_userRepository.Received(1).Update(user);
|
|
await _unitOfWork.Received(1).CommitAsync();
|
|
}
|
|
|
|
[Fact]
|
|
public async Task ValidateRefreshTokenAsync_ShouldReturnNull_WhenUserNotFound()
|
|
{
|
|
_userRepository.GetUserByIdAsync(99).Returns((User?)null);
|
|
|
|
var result = await _sut.ValidateRefreshTokenAsync(99, "some-token");
|
|
|
|
Assert.Null(result);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task ValidateRefreshTokenAsync_ShouldReturnNull_WhenTokenMismatch()
|
|
{
|
|
var user = new User
|
|
{
|
|
Id = 1,
|
|
Username = "testuser",
|
|
Email = "test@example.com",
|
|
Password = "hash",
|
|
RefreshToken = "stored-token",
|
|
RefreshTokenExpiryTime = DateTime.UtcNow.AddDays(1)
|
|
};
|
|
_userRepository.GetUserByIdAsync(1).Returns(user);
|
|
|
|
var result = await _sut.ValidateRefreshTokenAsync(1, "wrong-token");
|
|
|
|
Assert.Null(result);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task ValidateRefreshTokenAsync_ShouldReturnNull_WhenTokenExpired()
|
|
{
|
|
var user = new User
|
|
{
|
|
Id = 1,
|
|
Username = "testuser",
|
|
Email = "test@example.com",
|
|
Password = "hash",
|
|
RefreshToken = "expired-token",
|
|
RefreshTokenExpiryTime = DateTime.UtcNow.AddDays(-1)
|
|
};
|
|
_userRepository.GetUserByIdAsync(1).Returns(user);
|
|
|
|
var result = await _sut.ValidateRefreshTokenAsync(1, "expired-token");
|
|
|
|
Assert.Null(result);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task ValidateRefreshTokenAsync_ShouldReturnUser_WhenTokenValid()
|
|
{
|
|
var user = new User
|
|
{
|
|
Id = 1,
|
|
Username = "testuser",
|
|
Email = "test@example.com",
|
|
Password = "hash",
|
|
RefreshToken = "valid-token",
|
|
RefreshTokenExpiryTime = DateTime.UtcNow.AddDays(1)
|
|
};
|
|
_userRepository.GetUserByIdAsync(1).Returns(user);
|
|
|
|
var result = await _sut.ValidateRefreshTokenAsync(1, "valid-token");
|
|
|
|
Assert.NotNull(result);
|
|
Assert.Equal(1, result.Id);
|
|
}
|
|
}
|