using Application.Common.Results; using Application.DTOs; using Application.Errors; using Application.Models; using Application.Services; using Application.Validators; using Domain.Entities; using Domain.Interface; using NSubstitute; namespace Application.UnitTest.Services; public class UserServiceTests { private readonly IUnitOfWork _unitOfWork = Substitute.For(); private readonly IUserRepository _userRepository = Substitute.For(); private readonly IUserRoleRepository _userRoleRepository = Substitute.For(); private readonly UserService _sut; public UserServiceTests() { _sut = new UserService( _unitOfWork, new UserUpdateRequestValidator(), _userRepository, _userRoleRepository); } [Fact] public async Task GetAsync_ShouldReturnPagedResults() { var users = new List { new() { Id = 1, Username = "user1", Email = "user1@test.com", Password = "hash", UserRoles = [new UserRole { Role = new Role { Id = 1, Name = "Admin" } }] }, new() { Id = 2, Username = "user2", Email = "user2@test.com", Password = "hash", UserRoles = [new UserRole { Role = new Role { Id = 2, Name = "User" } }] } }; _userRepository.GetAllAsync().Returns(users); var result = await _sut.GetAsync(1, 10); Assert.True(result.IsSuccess); Assert.Equal(2, result.Value.Items.Count); Assert.Equal(2, result.Value.TotalCount); } [Fact] public async Task UpdateAsync_ShouldReturnSuccess_WhenRequestIsValid() { var request = new UserUpdateRequest(1, "updateduser", "updated@test.com"); var user = new User { Id = 1, Username = "olduser", Email = "old@test.com", Password = "hash" }; _userRepository.GetByIdAsync(request.Id).Returns(user); var result = await _sut.UpdateAsync(request); Assert.True(result.IsSuccess); Assert.Equal(request.Username, user.Username); Assert.Equal(request.Email, user.Email); _userRepository.Received(1).Update(user); await _unitOfWork.Received(1).CommitAsync(); } [Fact] public async Task UpdateAsync_ShouldReturnFailure_WhenValidationFails() { var request = new UserUpdateRequest(0, "", ""); var result = await _sut.UpdateAsync(request); Assert.True(result.IsFailure); Assert.Equal(ErrorTypeConstant.ValidationError, result.Error.Code); } [Fact] public async Task UpdateAsync_ShouldReturnFailure_WhenUserNotFound() { var request = new UserUpdateRequest(99, "user", "user@test.com"); _userRepository.GetByIdAsync(request.Id).Returns((User?)null); var result = await _sut.UpdateAsync(request); Assert.True(result.IsFailure); Assert.Equal(UserError.UserNotFound, result.Error); } [Fact] public async Task DeleteAsync_ShouldReturnSuccess_WhenUserExists() { var user = new User { Id = 2, Username = "user2", Email = "user2@test.com", Password = "hash" }; _userRepository.GetByIdAsync(2).Returns(user); var result = await _sut.DeleteAsync(2, 1); Assert.True(result.IsSuccess); _userRepository.Received(1).Delete(user); await _unitOfWork.Received(1).CommitAsync(); } [Fact] public async Task DeleteAsync_ShouldReturnFailure_WhenDeletingYourself() { var result = await _sut.DeleteAsync(1, 1); Assert.True(result.IsFailure); Assert.Equal(UserError.CannotDeleteYourself, result.Error); } [Fact] public async Task DeleteAsync_ShouldReturnFailure_WhenUserNotFound() { _userRepository.GetByIdAsync(99).Returns((User?)null); var result = await _sut.DeleteAsync(99, 1); Assert.True(result.IsFailure); Assert.Equal(UserError.UserNotFound, result.Error); } [Fact] public async Task GetUserByIdAsync_ShouldReturnUser_WhenUserExists() { var user = new User { Id = 1, Username = "testuser", Email = "test@test.com", Password = "hash", UserRoles = [new UserRole { Role = new Role { Id = 1, Name = "Admin" } }] }; _userRepository.GetByIdAsync(1).Returns(user); var result = await _sut.GetUserByIdAsync(1); Assert.True(result.IsSuccess); Assert.Equal(user.Id, result.Value.Id); Assert.Equal(user.Username, result.Value.Username); Assert.Equal(user.Email, result.Value.Email); } [Fact] public async Task GetUserByIdAsync_ShouldReturnFailure_WhenUserNotFound() { _userRepository.GetByIdAsync(99).Returns((User?)null); var result = await _sut.GetUserByIdAsync(99); Assert.True(result.IsFailure); Assert.Equal(UserError.UserNotFound, result.Error); } [Fact] public async Task AssignRoleAsync_ShouldReturnSuccess_WhenUserDoesNotHaveRole() { var request = new AssingRoleRequest(1, 2); _userRoleRepository.HasRoleAsync(request.UserId, request.RoleId).Returns(false); _userRoleRepository.AddRoleAsync(request.UserId, request.RoleId).Returns(true); var result = await _sut.AssignRoleAsync(request); Assert.True(result.IsSuccess); } [Fact] public async Task AssignRoleAsync_ShouldReturnFailure_WhenUserAlreadyHasRole() { var request = new AssingRoleRequest(1, 2); _userRoleRepository.HasRoleAsync(request.UserId, request.RoleId).Returns(true); var result = await _sut.AssignRoleAsync(request); Assert.True(result.IsFailure); Assert.Equal(UserError.UserAlreadyHasRole, result.Error); } [Fact] public async Task AssignRoleAsync_ShouldReturnFailure_WhenAddRoleFails() { var request = new AssingRoleRequest(1, 2); _userRoleRepository.HasRoleAsync(request.UserId, request.RoleId).Returns(false); _userRoleRepository.AddRoleAsync(request.UserId, request.RoleId).Returns(false); var result = await _sut.AssignRoleAsync(request); Assert.True(result.IsFailure); Assert.Equal(UserError.FailedToAssignRole, result.Error); } [Fact] public async Task RevokeRoleAsync_ShouldReturnSuccess_WhenUserHasRole() { var request = new AssingRoleRequest(1, 2); _userRoleRepository.HasRoleAsync(request.UserId, request.RoleId).Returns(true); _userRoleRepository.RemoveRoleAsync(request.UserId, request.RoleId).Returns(true); var result = await _sut.RevokeRoleAsync(request); Assert.True(result.IsSuccess); } [Fact] public async Task RevokeRoleAsync_ShouldReturnFailure_WhenUserHasNoRole() { var request = new AssingRoleRequest(1, 2); _userRoleRepository.HasRoleAsync(request.UserId, request.RoleId).Returns(false); var result = await _sut.RevokeRoleAsync(request); Assert.True(result.IsFailure); Assert.Equal(UserError.UserHasNoRole, result.Error); } [Fact] public async Task RevokeRoleAsync_ShouldReturnFailure_WhenRemoveRoleFails() { var request = new AssingRoleRequest(1, 2); _userRoleRepository.HasRoleAsync(request.UserId, request.RoleId).Returns(true); _userRoleRepository.RemoveRoleAsync(request.UserId, request.RoleId).Returns(false); var result = await _sut.RevokeRoleAsync(request); Assert.True(result.IsFailure); Assert.Equal(UserError.FailedToRevokeRole, result.Error); } }