using System; using System.Collections.Generic; using System.Threading.Tasks; using AutoMapper; using Entities.Contracts; using Entities.DTO; using Microsoft.AspNetCore.Identity; using Moq; using SharedDATA.Api; using TechHelper.Features; using TechHelper.Services.Beta; using Xunit; namespace TechHelper.Server.Tests { public class UserServicesTests { private readonly Mock _unitOfWorkMock; private readonly Mock _classServiceMock; private readonly Mock> _userManagerMock; private readonly Mock _mapperMock; private readonly Mock _emailSenderMock; private readonly UserServices _userServices; public UserServicesTests() { _unitOfWorkMock = new Mock(); _classServiceMock = new Mock(); _userManagerMock = new Mock>( Mock.Of>(), null, null, null, null, null, null, null, null); _mapperMock = new Mock(); _emailSenderMock = new Mock(); _userServices = new UserServices( _unitOfWorkMock.Object, _classServiceMock.Object, _userManagerMock.Object, _mapperMock.Object, _emailSenderMock.Object); } [Fact] public async Task RegisterNewUserAsync_WhenEmailAlreadyExists_ReturnsErrorMessage() { // Arrange var registrationDto = new UserForRegistrationDto { Email = "user@example.com", Password = "wx1998WX!", ConfirmPassword = "wx1998WX!", DisplayName = "Test User", Roles = UserRoles.Student }; var existingUser = new User { Email = "user@example.com" }; _userManagerMock.Setup(x => x.FindByEmailAsync(registrationDto.Email)) .ReturnsAsync(existingUser); // Act var result = await _userServices.RegisterNewUserAsync(registrationDto); // Assert Assert.False(result.Status); Assert.Contains("此电子邮件地址已被注册", result.Message); } [Fact] public async Task RegisterNewUserAsync_WhenUserCreationFails_ReturnsErrorWithErrors() { // Arrange var registrationDto = new UserForRegistrationDto { Email = "test@example.com", Password = "Password123!", ConfirmPassword = "Password123!", DisplayName = "Test User", Roles = UserRoles.Student }; _userManagerMock.Setup(x => x.FindByEmailAsync(registrationDto.Email)) .ReturnsAsync((User)null!); var user = new User(); _mapperMock.Setup(x => x.Map(registrationDto)) .Returns(user); _userManagerMock.Setup(x => x.CreateAsync(user, registrationDto.Password)) .ReturnsAsync(IdentityResult.Failed(new IdentityError { Description = "Password too weak" })); // Act var result = await _userServices.RegisterNewUserAsync(registrationDto); // Assert Assert.False(result.Status); Assert.NotNull(result.Result); Assert.IsType>(result.Result); } [Fact] public async Task RegisterNewUserAsync_WhenUserCreatedButNotFound_ReturnsErrorMessage() { // Arrange var registrationDto = new UserForRegistrationDto { Email = "test@example.com", Password = "Password123!", ConfirmPassword = "Password123!", DisplayName = "Test User", Roles = UserRoles.Student }; _userManagerMock.Setup(x => x.FindByEmailAsync(registrationDto.Email)) .ReturnsAsync((User)null!); var user = new User(); _mapperMock.Setup(x => x.Map(registrationDto)) .Returns(user); var identityResult = IdentityResult.Success; _userManagerMock.Setup(x => x.CreateAsync(user, registrationDto.Password)) .ReturnsAsync(identityResult); _userManagerMock.Setup(x => x.FindByEmailAsync(user.Email)) .ReturnsAsync((User)null!); // Act var result = await _userServices.RegisterNewUserAsync(registrationDto); // Assert Assert.False(result.Status); Assert.Contains("注册失败,请联系管理员", result.Message); } [Fact] public async Task RegisterNewUserAsync_WhenRoleAssignmentFails_ReturnsError() { // Arrange var registrationDto = new UserForRegistrationDto { Email = "test@example.com", Password = "Password123!", ConfirmPassword = "Password123!", DisplayName = "Test User", Roles = UserRoles.Student }; _userManagerMock.Setup(x => x.FindByEmailAsync(registrationDto.Email)) .ReturnsAsync((User)null!); var user = new User(); _mapperMock.Setup(x => x.Map(registrationDto)) .Returns(user); var identityResult = IdentityResult.Success; _userManagerMock.Setup(x => x.CreateAsync(user, registrationDto.Password)) .ReturnsAsync(identityResult); var createdUser = new User { Id = Guid.NewGuid(), Email = registrationDto.Email }; _userManagerMock.Setup(x => x.FindByEmailAsync(user.Email)) .ReturnsAsync(createdUser); _userManagerMock.Setup(x => x.AddToRoleAsync(createdUser, registrationDto.Roles.ToString())) .ReturnsAsync(IdentityResult.Failed(new IdentityError { Description = "Role assignment failed" })); // Act var result = await _userServices.RegisterNewUserAsync(registrationDto); // Assert Assert.False(result.Status); Assert.NotNull(result.Result); Assert.IsType>(result.Result); } [Fact] public async Task RegisterNewUserAsync_WhenClassRegistrationFails_DeletesUserAndReturnsError() { // Arrange var registrationDto = new UserForRegistrationDto { Email = "test@example.com", Password = "Password123!", ConfirmPassword = "Password123!", DisplayName = "Test User", Roles = UserRoles.Student, RegisterUserToClassDto = new RegisterUserToClassDto { UserId = Guid.NewGuid(), ClassId = Guid.NewGuid() } }; _userManagerMock.Setup(x => x.FindByEmailAsync(registrationDto.Email)) .ReturnsAsync((User)null!); var user = new User(); _mapperMock.Setup(x => x.Map(registrationDto)) .Returns(user); var identityResult = IdentityResult.Success; _userManagerMock.Setup(x => x.CreateAsync(user, registrationDto.Password)) .ReturnsAsync(identityResult); var createdUser = new User { Id = Guid.NewGuid(), Email = registrationDto.Email }; _userManagerMock.Setup(x => x.FindByEmailAsync(user.Email)) .ReturnsAsync(createdUser); _userManagerMock.Setup(x => x.AddToRoleAsync(createdUser, registrationDto.Roles.ToString())) .ReturnsAsync(IdentityResult.Success); _classServiceMock.Setup(x => x.UserRegister(registrationDto.RegisterUserToClassDto)) .ReturnsAsync(new ApiResponse(false, "Class registration failed")); // Act var result = await _userServices.RegisterNewUserAsync(registrationDto); // Assert Assert.False(result.Status); Assert.Contains("Class registration failed", result.Message); // Verify that the user was deleted _userManagerMock.Verify(x => x.DeleteAsync(createdUser), Times.Once); } [Fact] public async Task RegisterNewUserAsync_WhenAllStepsSucceed_ReturnsSuccess() { // Arrange var registrationDto = new UserForRegistrationDto { Email = "test@example.com", Password = "Password123!", ConfirmPassword = "Password123!", DisplayName = "Test User", Roles = UserRoles.Student, RegisterUserToClassDto = new RegisterUserToClassDto { UserId = Guid.NewGuid(), ClassId = Guid.NewGuid() } }; _userManagerMock.Setup(x => x.FindByEmailAsync(registrationDto.Email)) .ReturnsAsync((User)null!); var user = new User(); _mapperMock.Setup(x => x.Map(registrationDto)) .Returns(user); var identityResult = IdentityResult.Success; _userManagerMock.Setup(x => x.CreateAsync(user, registrationDto.Password)) .ReturnsAsync(identityResult); var createdUser = new User { Id = Guid.NewGuid(), Email = registrationDto.Email }; _userManagerMock.Setup(x => x.FindByEmailAsync(user.Email)) .ReturnsAsync(createdUser); _userManagerMock.Setup(x => x.AddToRoleAsync(createdUser, registrationDto.Roles.ToString())) .ReturnsAsync(IdentityResult.Success); _classServiceMock.Setup(x => x.UserRegister(registrationDto.RegisterUserToClassDto)) .ReturnsAsync(new ApiResponse(true, "操作成功。")); // Act var result = await _userServices.RegisterNewUserAsync(registrationDto); // Assert Assert.True(result.Status); Assert.Equal("操作成功。", result.Message); } [Fact] public async Task RegisterNewUserAsync_WhenExceptionOccurs_DeletesUserAndReturnsError() { // Arrange var registrationDto = new UserForRegistrationDto { Email = "test@example.com", Password = "Password123!", ConfirmPassword = "Password123!", DisplayName = "Test User", Roles = UserRoles.Student }; _userManagerMock.Setup(x => x.FindByEmailAsync(registrationDto.Email)) .ReturnsAsync((User)null!); var user = new User(); _mapperMock.Setup(x => x.Map(registrationDto)) .Returns(user); _userManagerMock.Setup(x => x.CreateAsync(user, registrationDto.Password)) .ThrowsAsync(new Exception("Database error")); var createdUser = new User { Id = Guid.NewGuid(), Email = registrationDto.Email }; _userManagerMock.Setup(x => x.FindByEmailAsync(registrationDto.Email)) .ReturnsAsync(createdUser); // Act var result = await _userServices.RegisterNewUserAsync(registrationDto); // Assert Assert.False(result.Status); Assert.Contains("注册过程中发生错误", result.Message); // Verify that the user was deleted _userManagerMock.Verify(x => x.DeleteAsync(createdUser), Times.Once); } [Fact] public async Task RegisterNewUserAsync_SetsCorrectUserProperties() { // Arrange var registrationDto = new UserForRegistrationDto { Email = "test@example.com", Password = "Password123!", ConfirmPassword = "Password123!", DisplayName = "Test User", Roles = UserRoles.Teacher }; _userManagerMock.Setup(x => x.FindByEmailAsync(registrationDto.Email)) .ReturnsAsync((User)null!); var mappedUser = new User(); _mapperMock.Setup(x => x.Map(registrationDto)) .Returns(mappedUser); // Act await _userServices.RegisterNewUserAsync(registrationDto); // Assert Assert.Equal(registrationDto.Email, mappedUser.UserName); Assert.Equal(registrationDto.DisplayName, mappedUser.DisplayName); Assert.Equal(registrationDto.Roles, mappedUser.Role); Assert.False(mappedUser.EmailConfirmed); } } }