diff --git a/Haoliang.Tests/AuthServiceTests.cs b/Haoliang.Tests/AuthServiceTests.cs new file mode 100644 index 0000000..1ab521f --- /dev/null +++ b/Haoliang.Tests/AuthServiceTests.cs @@ -0,0 +1,134 @@ +using Xunit; +using Moq; +using FluentAssertions; +using Haoliang.Core.Services; +using Haoliang.Models.User; +using Haoliang.Data.Repositories; + +namespace Haoliang.Tests; + +public class AuthServiceTests +{ + private readonly Mock _mockUserRepository; + private readonly Mock _mockCacheService; + private readonly AuthService _authService; + + public AuthServiceTests() + { + _mockUserRepository = new Mock(); + _mockCacheService = new Mock(); + _authService = new AuthService(_mockUserRepository.Object, _mockCacheService.Object); + } + + [Fact] + public async Task LoginAsync_ReturnsSuccess_WhenCredentialsValid() + { + var request = new LoginRequest { Username = "admin", Password = "password" }; + var user = new User + { + Id = 1, + Username = "admin", + RealName = "Administrator", + Role = new Role { RoleName = "Admin", Permissions = new List { "read", "write" } } + }; + _mockUserRepository.Setup(r => r.AuthenticateAsync("admin", "password")).ReturnsAsync(user); + + var result = await _authService.LoginAsync(request); + + result.Success.Should().BeTrue(); + result.User.Should().NotBeNull(); + result.User!.Username.Should().Be("admin"); + result.Permissions.Should().Contain("read"); + } + + [Fact] + public async Task LoginAsync_ReturnsFailure_WhenCredentialsInvalid() + { + var request = new LoginRequest { Username = "admin", Password = "wrongpassword" }; + _mockUserRepository.Setup(r => r.AuthenticateAsync("admin", "wrongpassword")).ReturnsAsync((User?)null); + + var result = await _authService.LoginAsync(request); + + result.Success.Should().BeFalse(); + result.Message.Should().Be("用户名或密码错误"); + } + + [Fact] + public async Task LogoutAsync_ReturnsTrue() + { + var result = await _authService.LogoutAsync(1); + + result.Should().BeTrue(); + } + + [Fact] + public async Task RefreshTokenAsync_ReturnsNull() + { + var result = await _authService.RefreshTokenAsync("someRefreshToken"); + + result.Should().BeNull(); + } + + [Fact] + public async Task UsernameExistsAsync_ReturnsTrue_WhenExists() + { + _mockUserRepository.Setup(r => r.UsernameExistsAsync("admin")).ReturnsAsync(true); + + var result = await _authService.UsernameExistsAsync("admin"); + + result.Should().BeTrue(); + } + + [Fact] + public async Task UsernameExistsAsync_ReturnsFalse_WhenNotExists() + { + _mockUserRepository.Setup(r => r.UsernameExistsAsync("nonexistent")).ReturnsAsync(false); + + var result = await _authService.UsernameExistsAsync("nonexistent"); + + result.Should().BeFalse(); + } + + [Fact] + public async Task EmailExistsAsync_ReturnsTrue_WhenExists() + { + _mockUserRepository.Setup(r => r.EmailExistsAsync("admin@example.com")).ReturnsAsync(true); + + var result = await _authService.EmailExistsAsync("admin@example.com"); + + result.Should().BeTrue(); + } + + [Fact] + public async Task EmailExistsAsync_ReturnsFalse_WhenNotExists() + { + _mockUserRepository.Setup(r => r.EmailExistsAsync("nonexistent@example.com")).ReturnsAsync(false); + + var result = await _authService.EmailExistsAsync("nonexistent@example.com"); + + result.Should().BeFalse(); + } + + [Fact] + public async Task GetUserByIdAsync_ReturnsUser_WhenExists() + { + var user = new User { Id = 1, Username = "admin", RealName = "Administrator" }; + _mockUserRepository.Setup(r => r.GetByIdAsync(1)).ReturnsAsync(user); + + var result = await _authService.GetUserByIdAsync(1); + + result.Should().NotBeNull(); + result!.Id.Should().Be(1); + result.Username.Should().Be("admin"); + } + + [Fact] + public async Task GetUserByIdAsync_ReturnsNull_WhenNotExists() + { + _mockUserRepository.Setup(r => r.GetByIdAsync(999)).ReturnsAsync((User?)null); + + var result = await _authService.GetUserByIdAsync(999); + + result.Should().BeNull(); + } +} \ No newline at end of file diff --git a/Haoliang.Tests/DataStorageServiceTests.cs b/Haoliang.Tests/DataStorageServiceTests.cs new file mode 100644 index 0000000..f8c81d0 --- /dev/null +++ b/Haoliang.Tests/DataStorageServiceTests.cs @@ -0,0 +1,98 @@ +using Xunit; +using Moq; +using FluentAssertions; +using Microsoft.Extensions.Logging; +using Haoliang.Core.Services; +using Haoliang.Models.Device; +using Haoliang.Models.Production; +using Haoliang.Data.Repositories; + +namespace Haoliang.Tests; + +public class DataStorageServiceTests +{ + private readonly Mock> _mockLogger; + private readonly Mock _mockDeviceRepository; + private readonly DataStorageService _dataStorageService; + + public DataStorageServiceTests() + { + _mockLogger = new Mock>(); + _mockDeviceRepository = new Mock(); + + _dataStorageService = new DataStorageService( + _mockLogger.Object, + _mockDeviceRepository.Object); + } + + [Fact] + public async Task StoreDeviceDataAsync_CallsUpdateDeviceStatus() + { + var data = new ParsedDeviceData + { + DeviceId = 1, + DeviceName = "Test Device", + Timestamp = DateTime.Now + }; + _mockDeviceRepository.Setup(r => r.UpdateDeviceStatusAsync(1, true, true)).Returns(Task.CompletedTask); + + await _dataStorageService.StoreDeviceDataAsync(data); + + _mockDeviceRepository.Verify(r => r.UpdateDeviceStatusAsync(1, true, true), Times.Once); + } + + [Fact] + public async Task StoreDeviceDataAsync_CompletesSuccessfully() + { + var data = new ParsedDeviceData { DeviceId = 1, DeviceName = "Test" }; + _mockDeviceRepository.Setup(r => r.UpdateDeviceStatusAsync(It.IsAny(), It.IsAny(), It.IsAny())).Returns(Task.CompletedTask); + + var action = async () => await _dataStorageService.StoreDeviceDataAsync(data); + + await action.Should().NotThrowAsync(); + } + + [Fact] + public async Task StoreDeviceDataBatchAsync_ProcessesAllDevices() + { + var dataList = new List + { + new ParsedDeviceData { DeviceId = 1, DeviceName = "Device 1" }, + new ParsedDeviceData { DeviceId = 2, DeviceName = "Device 2" }, + new ParsedDeviceData { DeviceId = 3, DeviceName = "Device 3" } + }; + _mockDeviceRepository.Setup(r => r.UpdateDeviceStatusAsync(It.IsAny(), It.IsAny(), It.IsAny())).Returns(Task.CompletedTask); + + await _dataStorageService.StoreDeviceDataBatchAsync(dataList); + + _mockDeviceRepository.Verify(r => r.UpdateDeviceStatusAsync(1, true, true), Times.Once); + _mockDeviceRepository.Verify(r => r.UpdateDeviceStatusAsync(2, true, true), Times.Once); + _mockDeviceRepository.Verify(r => r.UpdateDeviceStatusAsync(3, true, true), Times.Once); + } + + [Fact] + public async Task StoreDeviceDataBatchAsync_HandlesEmptyList() + { + var dataList = new List(); + + var action = async () => await _dataStorageService.StoreDeviceDataBatchAsync(dataList); + + await action.Should().NotThrowAsync(); + } + + [Fact] + public async Task StoreProductionRecordAsync_CompletesSuccessfully() + { + var record = new ProductionRecord + { + DeviceId = 1, + ProgramName = "PROGRAM001", + Quantity = 100, + ProductionDate = DateTime.Now + }; + + var action = async () => await _dataStorageService.StoreProductionRecordAsync(record); + + await action.Should().NotThrowAsync(); + } +} \ No newline at end of file diff --git a/Haoliang.Tests/DeviceCollectionServiceTests.cs b/Haoliang.Tests/DeviceCollectionServiceTests.cs new file mode 100644 index 0000000..f9e5e30 --- /dev/null +++ b/Haoliang.Tests/DeviceCollectionServiceTests.cs @@ -0,0 +1,166 @@ +using Xunit; +using Moq; +using FluentAssertions; +using Microsoft.Extensions.Logging; +using Haoliang.Core.Services; +using Haoliang.Models.Device; +using Haoliang.Data.Repositories; +using DeviceStatus = Haoliang.Models.Device.DeviceCurrentStatus; + +namespace Haoliang.Tests; + +public class DeviceCollectionServiceTests +{ + private readonly Mock> _mockLogger; + private readonly Mock _mockPingService; + private readonly Mock _mockDataParserService; + private readonly Mock _mockDeviceRepository; + private readonly DeviceCollectionService _deviceCollectionService; + + public DeviceCollectionServiceTests() + { + _mockLogger = new Mock>(); + _mockPingService = new Mock(); + _mockDataParserService = new Mock(); + _mockDeviceRepository = new Mock(); + + _deviceCollectionService = new DeviceCollectionService( + _mockLogger.Object, + _mockPingService.Object, + _mockDataParserService.Object, + _mockDeviceRepository.Object); + } + + [Fact] + public async Task GetAllDevicesAsync_ReturnsDevicesFromRepository() + { + var devices = new List + { + new CNCDevice { Id = 1, DeviceCode = "CNC001", DeviceName = "Device 1" }, + new CNCDevice { Id = 2, DeviceCode = "CNC002", DeviceName = "Device 2" } + }; + _mockDeviceRepository.Setup(r => r.GetAllAsync()).ReturnsAsync(devices); + + var result = await _deviceCollectionService.GetAllDevicesAsync(); + + result.Should().HaveCount(2); + result.Should().BeEquivalentTo(devices); + } + + [Fact] + public async Task GetDeviceByIdAsync_ReturnsDevice_WhenExists() + { + var device = new CNCDevice { Id = 1, DeviceCode = "CNC001", DeviceName = "Device 1" }; + _mockDeviceRepository.Setup(r => r.GetByIdAsync(1)).ReturnsAsync(device); + + var result = await _deviceCollectionService.GetDeviceByIdAsync(1); + + result.Should().NotBeNull(); + result!.Id.Should().Be(1); + } + + [Fact] + public async Task GetDeviceByIdAsync_ReturnsNull_WhenNotExists() + { + _mockDeviceRepository.Setup(r => r.GetByIdAsync(999)).ReturnsAsync((CNCDevice?)null); + + var result = await _deviceCollectionService.GetDeviceByIdAsync(999); + + result.Should().BeNull(); + } + + [Fact] + public async Task CreateDeviceAsync_SetsCreatedAtAndUpdatedAt() + { + var device = new CNCDevice { DeviceCode = "CNC003", DeviceName = "New Device" }; + _mockDeviceRepository.Setup(r => r.AddAsync(It.IsAny())).Returns(Task.CompletedTask); + _mockDeviceRepository.Setup(r => r.SaveAsync()).ReturnsAsync(1); + + var beforeCreate = DateTime.UtcNow; + var result = await _deviceCollectionService.CreateDeviceAsync(device); + var afterCreate = DateTime.UtcNow; + + result.CreatedAt.Should().BeOnOrAfter(beforeCreate); + result.CreatedAt.Should().BeOnOrBefore(afterCreate); + result.UpdatedAt.Should().BeOnOrAfter(beforeCreate); + result.UpdatedAt.Should().BeOnOrBefore(afterCreate); + } + + [Fact] + public async Task UpdateDeviceAsync_UpdatesDevice_WhenExists() + { + var device = new CNCDevice { Id = 1, DeviceCode = "CNC001", DeviceName = "Updated Device" }; + _mockDeviceRepository.Setup(r => r.Update(It.IsAny())).Verifiable(); + _mockDeviceRepository.Setup(r => r.SaveAsync()).ReturnsAsync(1); + + var result = await _deviceCollectionService.UpdateDeviceAsync(device); + + result.Should().NotBeNull(); + result!.DeviceName.Should().Be("Updated Device"); + } + + [Fact] + public async Task UpdateDeviceAsync_ReturnsNull_WhenNotExists() + { + var device = new CNCDevice { Id = 999 }; + _mockDeviceRepository.Setup(r => r.SaveAsync()).ReturnsAsync(0); + + var result = await _deviceCollectionService.UpdateDeviceAsync(device); + + result.Should().BeNull(); + } + + [Fact] + public async Task DeleteDeviceAsync_ReturnsTrue_WhenDeviceExists() + { + var device = new CNCDevice { Id = 1 }; + _mockDeviceRepository.Setup(r => r.GetByIdAsync(1)).ReturnsAsync(device); + _mockDeviceRepository.Setup(r => r.Remove(device)).Verifiable(); + _mockDeviceRepository.Setup(r => r.SaveAsync()).ReturnsAsync(1); + + var result = await _deviceCollectionService.DeleteDeviceAsync(1); + + result.Should().BeTrue(); + } + + [Fact] + public async Task DeleteDeviceAsync_ReturnsFalse_WhenDeviceNotExists() + { + _mockDeviceRepository.Setup(r => r.GetByIdAsync(999)).ReturnsAsync((CNCDevice?)null); + + var result = await _deviceCollectionService.DeleteDeviceAsync(999); + + result.Should().BeFalse(); + } + + [Fact] + public async Task CollectDeviceAsync_Skips_WhenDeviceNotExists() + { + _mockDeviceRepository.Setup(r => r.GetByIdAsync(999)).ReturnsAsync((CNCDevice?)null); + + await _deviceCollectionService.CollectDeviceAsync(999); + + _mockPingService.Verify(p => p.PingAsync(It.IsAny(), It.IsAny()), Times.Never); + } + + [Fact] + public async Task CollectDeviceAsync_Skips_WhenDeviceNotAvailable() + { + var device = new CNCDevice { Id = 1, IsAvailable = false }; + _mockDeviceRepository.Setup(r => r.GetByIdAsync(1)).ReturnsAsync(device); + + await _deviceCollectionService.CollectDeviceAsync(1); + + _mockPingService.Verify(p => p.PingAsync(It.IsAny(), It.IsAny()), Times.Never); + } + + [Fact] + public async Task GetDeviceStatusAsync_ReturnsDeviceStatus() + { + var result = await _deviceCollectionService.GetDeviceStatusAsync(1); + + result.Should().NotBeNull(); + result.DeviceId.Should().Be(1); + result.Timestamp.Should().BeCloseTo(DateTime.UtcNow, TimeSpan.FromSeconds(1)); + } +} \ No newline at end of file diff --git a/Haoliang.Tests/UserServiceTests.cs b/Haoliang.Tests/UserServiceTests.cs new file mode 100644 index 0000000..3abab51 --- /dev/null +++ b/Haoliang.Tests/UserServiceTests.cs @@ -0,0 +1,176 @@ +using Xunit; +using Moq; +using FluentAssertions; +using Haoliang.Core.Services; +using Haoliang.Models.User; +using Haoliang.Data.Repositories; + +namespace Haoliang.Tests; + +public class UserServiceTests +{ + private readonly Mock _mockUserRepository; + private readonly UserService _userService; + + public UserServiceTests() + { + _mockUserRepository = new Mock(); + _userService = new UserService(_mockUserRepository.Object); + } + + [Fact] + public async Task CreateUserAsync_SetsCreatedAtAndUpdatedAt() + { + var user = new User { Username = "newuser", RealName = "New User", Email = "new@example.com" }; + _mockUserRepository.Setup(r => r.AddAsync(It.IsAny())).Returns(Task.CompletedTask); + _mockUserRepository.Setup(r => r.SaveAsync()).ReturnsAsync(1); + + var beforeCreate = DateTime.Now; + var result = await _userService.CreateUserAsync(user); + var afterCreate = DateTime.Now; + + result.CreatedAt.Should().BeOnOrAfter(beforeCreate); + result.CreatedAt.Should().BeOnOrBefore(afterCreate); + } + + [Fact] + public async Task GetUserByIdAsync_ReturnsUserViewModel_WhenExists() + { + var user = new User + { + Id = 1, + Username = "admin", + RealName = "Administrator", + Email = "admin@example.com", + Role = new Role { RoleName = "Admin" } + }; + _mockUserRepository.Setup(r => r.GetByIdAsync(1)).ReturnsAsync(user); + + var result = await _userService.GetUserByIdAsync(1); + + result.Should().NotBeNull(); + result!.Username.Should().Be("admin"); + result.RealName.Should().Be("Administrator"); + } + + [Fact] + public async Task GetUserByIdAsync_ReturnsNull_WhenNotExists() + { + _mockUserRepository.Setup(r => r.GetByIdAsync(999)).ReturnsAsync((User?)null); + + var result = await _userService.GetUserByIdAsync(999); + + result.Should().BeNull(); + } + + [Fact] + public async Task GetAllUsersAsync_ReturnsAllUsers() + { + var users = new List + { + new User { Id = 1, Username = "user1", RealName = "User 1" }, + new User { Id = 2, Username = "user2", RealName = "User 2" } + }; + _mockUserRepository.Setup(r => r.GetAllAsync()).ReturnsAsync(users); + + var result = await _userService.GetAllUsersAsync(); + + result.Should().HaveCount(2); + } + + [Fact] + public async Task UpdateUserAsync_UpdatesUser_WhenExists() + { + var existing = new User + { + Id = 1, + Username = "admin", + RealName = "Original Name", + Email = "original@example.com" + }; + var updateData = new User + { + RealName = "Updated Name", + Email = "updated@example.com", + Department = "IT", + RoleId = 2 + }; + + _mockUserRepository.Setup(r => r.GetByIdAsync(1)).ReturnsAsync(existing); + _mockUserRepository.Setup(r => r.Update(It.IsAny())).Verifiable(); + _mockUserRepository.Setup(r => r.SaveAsync()).ReturnsAsync(1); + + var result = await _userService.UpdateUserAsync(1, updateData); + + result.Should().NotBeNull(); + result!.RealName.Should().Be("Updated Name"); + result.Email.Should().Be("updated@example.com"); + } + + [Fact] + public async Task UpdateUserAsync_ReturnsNull_WhenNotExists() + { + _mockUserRepository.Setup(r => r.GetByIdAsync(999)).ReturnsAsync((User?)null); + + var result = await _userService.UpdateUserAsync(999, new User()); + + result.Should().BeNull(); + } + + [Fact] + public async Task ActivateUserAsync_ReturnsTrue_WhenUserExists() + { + var user = new User { Id = 1, IsActive = false }; + _mockUserRepository.Setup(r => r.GetByIdAsync(1)).ReturnsAsync(user); + _mockUserRepository.Setup(r => r.Update(It.IsAny())).Verifiable(); + _mockUserRepository.Setup(r => r.SaveAsync()).ReturnsAsync(1); + + var result = await _userService.ActivateUserAsync(1); + + result.Should().BeTrue(); + } + + [Fact] + public async Task ActivateUserAsync_ReturnsFalse_WhenUserNotExists() + { + _mockUserRepository.Setup(r => r.GetByIdAsync(999)).ReturnsAsync((User?)null); + + var result = await _userService.ActivateUserAsync(999); + + result.Should().BeFalse(); + } + + [Fact] + public async Task DeactivateUserAsync_ReturnsTrue_WhenUserExists() + { + var user = new User { Id = 1, IsActive = true }; + _mockUserRepository.Setup(r => r.GetByIdAsync(1)).ReturnsAsync(user); + _mockUserRepository.Setup(r => r.Update(It.IsAny())).Verifiable(); + _mockUserRepository.Setup(r => r.SaveAsync()).ReturnsAsync(1); + + var result = await _userService.DeactivateUserAsync(1); + + result.Should().BeTrue(); + } + + [Fact] + public async Task DeactivateUserAsync_ReturnsFalse_WhenUserNotExists() + { + _mockUserRepository.Setup(r => r.GetByIdAsync(999)).ReturnsAsync((User?)null); + + var result = await _userService.DeactivateUserAsync(999); + + result.Should().BeFalse(); + } + + [Fact] + public async Task ChangePasswordAsync_CallsRepository() + { + _mockUserRepository.Setup(r => r.ChangePasswordAsync(1, "old", "new")).ReturnsAsync(true); + + var result = await _userService.ChangePasswordAsync(1, "old", "new"); + + result.Should().BeTrue(); + _mockUserRepository.Verify(r => r.ChangePasswordAsync(1, "old", "new"), Times.Once); + } +} \ No newline at end of file