feat(api/web): 实现API请求签名验证功能并优化测试环境配置
refactor(db): 重构查询条件类到query目录下 test: 添加登录流程测试脚本和测试数据 chore: 添加crypto-js依赖用于签名验证 ci: 配置测试环境数据库和端口设置
This commit is contained in:
+245
@@ -0,0 +1,245 @@
|
||||
package cn.novalon.manage.sys.core.service.impl;
|
||||
|
||||
import cn.novalon.manage.common.util.StatusConstants;
|
||||
import cn.novalon.manage.sys.core.domain.SysUser;
|
||||
import cn.novalon.manage.sys.core.domain.SysRole;
|
||||
import cn.novalon.manage.sys.core.domain.UserRole;
|
||||
import cn.novalon.manage.sys.core.repository.ISysUserRepository;
|
||||
import cn.novalon.manage.sys.core.repository.ISysRoleRepository;
|
||||
import cn.novalon.manage.sys.core.repository.IUserRoleRepository;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.autoconfigure.data.r2dbc.DataR2dbcTest;
|
||||
import org.springframework.data.r2dbc.core.R2dbcEntityTemplate;
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.test.context.ActiveProfiles;
|
||||
import org.springframework.test.context.DynamicPropertyRegistry;
|
||||
import org.springframework.test.context.DynamicPropertySource;
|
||||
import org.testcontainers.containers.PostgreSQLContainer;
|
||||
import org.testcontainers.junit.jupiter.Container;
|
||||
import org.testcontainers.junit.jupiter.Testcontainers;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.test.StepVerifier;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Arrays;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
/**
|
||||
* 用户服务集成测试
|
||||
*
|
||||
* 使用Testcontainers进行PostgreSQL数据库集成测试
|
||||
*
|
||||
* @author 张翔
|
||||
* @date 2026-04-02
|
||||
*/
|
||||
@DataR2dbcTest
|
||||
@Testcontainers
|
||||
@ActiveProfiles("test")
|
||||
class SysUserServiceIntegrationTest {
|
||||
|
||||
@Container
|
||||
static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:15-alpine")
|
||||
.withDatabaseName("testdb")
|
||||
.withUsername("test")
|
||||
.withPassword("test");
|
||||
|
||||
@DynamicPropertySource
|
||||
static void postgresProperties(DynamicPropertyRegistry registry) {
|
||||
registry.add("spring.r2dbc.url", () ->
|
||||
String.format("r2dbc:postgresql://%s:%d/%s",
|
||||
postgres.getHost(),
|
||||
postgres.getFirstMappedPort(),
|
||||
postgres.getDatabaseName()));
|
||||
registry.add("spring.r2dbc.username", postgres::getUsername);
|
||||
registry.add("spring.r2dbc.password", postgres::getPassword);
|
||||
}
|
||||
|
||||
@Autowired
|
||||
private ISysUserRepository userRepository;
|
||||
|
||||
@Autowired
|
||||
private ISysRoleRepository roleRepository;
|
||||
|
||||
@Autowired
|
||||
private IUserRoleRepository userRoleRepository;
|
||||
|
||||
@Autowired
|
||||
private R2dbcEntityTemplate r2dbcEntityTemplate;
|
||||
|
||||
private SysUserService userService;
|
||||
private PasswordEncoder passwordEncoder;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
passwordEncoder = new BCryptPasswordEncoder(12);
|
||||
userService = new SysUserService(userRepository, roleRepository, userRoleRepository, passwordEncoder);
|
||||
|
||||
r2dbcEntityTemplate.delete(SysUser.class).all().block();
|
||||
r2dbcEntityTemplate.delete(SysRole.class).all().block();
|
||||
r2dbcEntityTemplate.delete(UserRole.class).all().block();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCreateAndFindUser() {
|
||||
SysUser user = new SysUser();
|
||||
user.setUsername("testuser");
|
||||
user.setPassword("password123");
|
||||
user.setEmail("test@example.com");
|
||||
user.setNickname("Test User");
|
||||
user.setPhone("13800138000");
|
||||
|
||||
StepVerifier.create(userService.createUser(user))
|
||||
.expectNextMatches(createdUser -> {
|
||||
assertNotNull(createdUser.getId());
|
||||
assertEquals("testuser", createdUser.getUsername());
|
||||
assertEquals("test@example.com", createdUser.getEmail());
|
||||
assertTrue(createdUser.getPassword().startsWith("$2b$"));
|
||||
assertEquals(StatusConstants.ENABLED, createdUser.getStatus());
|
||||
return true;
|
||||
})
|
||||
.verifyComplete();
|
||||
|
||||
StepVerifier.create(userService.findByUsername("testuser"))
|
||||
.expectNextMatches(foundUser -> {
|
||||
assertEquals("testuser", foundUser.getUsername());
|
||||
assertEquals("test@example.com", foundUser.getEmail());
|
||||
return true;
|
||||
})
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testUpdateUser() {
|
||||
SysUser user = new SysUser();
|
||||
user.setUsername("updateuser");
|
||||
user.setPassword("password123");
|
||||
user.setEmail("update@example.com");
|
||||
|
||||
SysUser createdUser = userService.createUser(user).block();
|
||||
assertNotNull(createdUser);
|
||||
|
||||
createdUser.setEmail("updated@example.com");
|
||||
createdUser.setNickname("Updated User");
|
||||
|
||||
StepVerifier.create(userService.updateUser(createdUser))
|
||||
.expectNextMatches(updatedUser -> {
|
||||
assertEquals("updated@example.com", updatedUser.getEmail());
|
||||
assertEquals("Updated User", updatedUser.getNickname());
|
||||
return true;
|
||||
})
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testDeleteUser() {
|
||||
SysUser user = new SysUser();
|
||||
user.setUsername("deleteuser");
|
||||
user.setPassword("password123");
|
||||
user.setEmail("delete@example.com");
|
||||
|
||||
SysUser createdUser = userService.createUser(user).block();
|
||||
assertNotNull(createdUser);
|
||||
|
||||
StepVerifier.create(userService.deleteUser(createdUser.getId()))
|
||||
.verifyComplete();
|
||||
|
||||
StepVerifier.create(userService.findById(createdUser.getId()))
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testChangePassword() {
|
||||
SysUser user = new SysUser();
|
||||
user.setUsername("pwduser");
|
||||
user.setPassword("oldPassword");
|
||||
user.setEmail("pwd@example.com");
|
||||
|
||||
SysUser createdUser = userService.createUser(user).block();
|
||||
assertNotNull(createdUser);
|
||||
|
||||
StepVerifier.create(userService.changePassword(createdUser.getId(), "oldPassword", "newPassword"))
|
||||
.expectNextMatches(updatedUser -> {
|
||||
assertNotEquals(createdUser.getPassword(), updatedUser.getPassword());
|
||||
assertTrue(passwordEncoder.matches("newPassword", updatedUser.getPassword()));
|
||||
return true;
|
||||
})
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testAssignRolesToUser() {
|
||||
SysRole role1 = new SysRole();
|
||||
role1.setRoleName("Test Role 1");
|
||||
role1.setRoleKey("test_role_1");
|
||||
role1.setStatus(1);
|
||||
|
||||
SysRole role2 = new SysRole();
|
||||
role2.setRoleName("Test Role 2");
|
||||
role2.setRoleKey("test_role_2");
|
||||
role2.setStatus(1);
|
||||
|
||||
SysRole createdRole1 = roleRepository.save(role1).block();
|
||||
SysRole createdRole2 = roleRepository.save(role2).block();
|
||||
assertNotNull(createdRole1);
|
||||
assertNotNull(createdRole2);
|
||||
|
||||
SysUser user = new SysUser();
|
||||
user.setUsername("roleuser");
|
||||
user.setPassword("password123");
|
||||
user.setEmail("role@example.com");
|
||||
|
||||
SysUser createdUser = userService.createUser(user).block();
|
||||
assertNotNull(createdUser);
|
||||
|
||||
StepVerifier.create(userService.assignRolesToUser(createdUser.getId(),
|
||||
Arrays.asList(createdRole1.getId(), createdRole2.getId())))
|
||||
.verifyComplete();
|
||||
|
||||
StepVerifier.create(userRoleRepository.findByUserId(createdUser.getId()).collectList())
|
||||
.expectNextMatches(userRoles -> {
|
||||
assertEquals(2, userRoles.size());
|
||||
return true;
|
||||
})
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFindAllUsers() {
|
||||
for (int i = 1; i <= 3; i++) {
|
||||
SysUser user = new SysUser();
|
||||
user.setUsername("user" + i);
|
||||
user.setPassword("password" + i);
|
||||
user.setEmail("user" + i + "@example.com");
|
||||
userService.createUser(user).block();
|
||||
}
|
||||
|
||||
StepVerifier.create(userService.findAll(false).collectList())
|
||||
.expectNextMatches(users -> {
|
||||
assertEquals(3, users.size());
|
||||
return true;
|
||||
})
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testExistsByUsername() {
|
||||
SysUser user = new SysUser();
|
||||
user.setUsername("existinguser");
|
||||
user.setPassword("password123");
|
||||
user.setEmail("existing@example.com");
|
||||
userService.createUser(user).block();
|
||||
|
||||
StepVerifier.create(userService.existsByUsername("existinguser"))
|
||||
.expectNext(true)
|
||||
.verifyComplete();
|
||||
|
||||
StepVerifier.create(userService.existsByUsername("nonexistinguser"))
|
||||
.expectNext(false)
|
||||
.verifyComplete();
|
||||
}
|
||||
}
|
||||
+261
-563
@@ -2,13 +2,18 @@ package cn.novalon.manage.sys.core.service.impl;
|
||||
|
||||
import cn.novalon.manage.common.util.StatusConstants;
|
||||
import cn.novalon.manage.sys.core.domain.SysUser;
|
||||
import cn.novalon.manage.sys.core.repository.ISysUserRepository;
|
||||
import cn.novalon.manage.sys.core.domain.SysRole;
|
||||
import cn.novalon.manage.sys.core.domain.UserRole;
|
||||
import cn.novalon.manage.common.dto.PageRequest;
|
||||
import cn.novalon.manage.common.dto.PageResponse;
|
||||
import cn.novalon.manage.sys.core.repository.ISysUserRepository;
|
||||
import cn.novalon.manage.sys.core.repository.ISysRoleRepository;
|
||||
import cn.novalon.manage.sys.core.repository.IUserRoleRepository;
|
||||
import cn.novalon.manage.sys.core.command.CreateUserCommand;
|
||||
import cn.novalon.manage.sys.core.command.UpdateUserCommand;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
@@ -17,576 +22,269 @@ import reactor.core.publisher.Mono;
|
||||
import reactor.test.StepVerifier;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.Arrays;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.ArgumentMatchers.isNull;
|
||||
import static org.mockito.ArgumentMatchers.anyLong;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
/**
|
||||
* 用户服务单元测试类
|
||||
* 用户服务单元测试
|
||||
*
|
||||
* @author 张翔
|
||||
* @date 2026-03-14
|
||||
* @date 2026-04-02
|
||||
*/
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class SysUserServiceTest {
|
||||
|
||||
@Mock
|
||||
private ISysUserRepository userRepository;
|
||||
|
||||
@Mock
|
||||
private cn.novalon.manage.sys.core.repository.ISysRoleRepository roleRepository;
|
||||
|
||||
@Mock
|
||||
private cn.novalon.manage.sys.core.repository.IUserRoleRepository userRoleRepository;
|
||||
|
||||
@Mock
|
||||
private PasswordEncoder passwordEncoder;
|
||||
|
||||
private SysUserService userService;
|
||||
|
||||
private SysUser testUser;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
userService = new SysUserService(userRepository, roleRepository, userRoleRepository, passwordEncoder);
|
||||
|
||||
testUser = new SysUser();
|
||||
testUser.setId(1L);
|
||||
testUser.setUsername("testuser");
|
||||
testUser.setPassword("encoded_password");
|
||||
testUser.setEmail("test@example.com");
|
||||
testUser.setRoleId(1L);
|
||||
testUser.setStatus(StatusConstants.ENABLED);
|
||||
testUser.setCreatedAt(LocalDateTime.now());
|
||||
testUser.setUpdatedAt(LocalDateTime.now());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFindById() {
|
||||
when(userRepository.findById(1L)).thenReturn(Mono.just(testUser));
|
||||
|
||||
StepVerifier.create(userService.findById(1L))
|
||||
.expectNext(testUser)
|
||||
.verifyComplete();
|
||||
|
||||
verify(userRepository).findById(1L);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFindAll() {
|
||||
when(userRepository.findAll()).thenReturn(Flux.just(testUser));
|
||||
|
||||
StepVerifier.create(userService.findAll())
|
||||
.expectNext(testUser)
|
||||
.verifyComplete();
|
||||
|
||||
verify(userRepository).findAll();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFindAll_IncludeDeleted() {
|
||||
when(userRepository.findAll()).thenReturn(Flux.just(testUser));
|
||||
|
||||
StepVerifier.create(userService.findAll(true))
|
||||
.expectNext(testUser)
|
||||
.verifyComplete();
|
||||
|
||||
verify(userRepository).findAll();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFindAll_ExcludeDeleted() {
|
||||
when(userRepository.findByDeletedAtIsNull()).thenReturn(Flux.just(testUser));
|
||||
|
||||
StepVerifier.create(userService.findAll(false))
|
||||
.expectNext(testUser)
|
||||
.verifyComplete();
|
||||
|
||||
verify(userRepository).findByDeletedAtIsNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFindUsersByPage() {
|
||||
PageRequest pageRequest = new PageRequest();
|
||||
pageRequest.setPage(0);
|
||||
pageRequest.setSize(10);
|
||||
pageRequest.setKeyword("test");
|
||||
|
||||
PageResponse<SysUser> pageResponse = new PageResponse<>();
|
||||
pageResponse.setContent(List.of(testUser));
|
||||
pageResponse.setTotalElements(1L);
|
||||
|
||||
when(userRepository.findByQueryWithPagination(isNull(), eq(pageRequest)))
|
||||
.thenReturn(Mono.just(pageResponse));
|
||||
|
||||
StepVerifier.create(userService.findUsersByPage(pageRequest))
|
||||
.expectNextMatches(response -> response.getTotalElements() == 1L)
|
||||
.verifyComplete();
|
||||
|
||||
verify(userRepository).findByQueryWithPagination(isNull(), eq(pageRequest));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFindUsersByPage_NoKeyword() {
|
||||
PageRequest pageRequest = new PageRequest();
|
||||
pageRequest.setPage(0);
|
||||
pageRequest.setSize(10);
|
||||
|
||||
PageResponse<SysUser> pageResponse = new PageResponse<>();
|
||||
pageResponse.setContent(List.of(testUser));
|
||||
pageResponse.setTotalElements(1L);
|
||||
|
||||
when(userRepository.findByQueryWithPagination(isNull(), eq(pageRequest)))
|
||||
.thenReturn(Mono.just(pageResponse));
|
||||
|
||||
StepVerifier.create(userService.findUsersByPage(pageRequest))
|
||||
.expectNextMatches(response -> response.getTotalElements() == 1L)
|
||||
.verifyComplete();
|
||||
|
||||
verify(userRepository).findByQueryWithPagination(isNull(), eq(pageRequest));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCount() {
|
||||
when(userRepository.count()).thenReturn(Mono.just(10L));
|
||||
|
||||
StepVerifier.create(userService.count())
|
||||
.expectNext(10L)
|
||||
.verifyComplete();
|
||||
|
||||
verify(userRepository).count();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFindByUsername() {
|
||||
when(userRepository.findByUsername("testuser")).thenReturn(Mono.just(testUser));
|
||||
|
||||
StepVerifier.create(userService.findByUsername("testuser"))
|
||||
.expectNext(testUser)
|
||||
.verifyComplete();
|
||||
|
||||
verify(userRepository).findByUsername("testuser");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCreateUser() {
|
||||
SysUser newUser = new SysUser();
|
||||
newUser.setUsername("newuser");
|
||||
newUser.setPassword("raw_password");
|
||||
newUser.setEmail("new@example.com");
|
||||
|
||||
when(passwordEncoder.encode("raw_password")).thenReturn("encoded_password");
|
||||
when(userRepository.save(any(SysUser.class))).thenReturn(Mono.just(testUser));
|
||||
|
||||
StepVerifier.create(userService.createUser(newUser))
|
||||
.expectNextMatches(user -> user.getPassword().equals("encoded_password") &&
|
||||
user.getStatus().equals(StatusConstants.ENABLED) &&
|
||||
user.getCreatedAt() != null)
|
||||
.verifyComplete();
|
||||
|
||||
ArgumentCaptor<SysUser> userCaptor = ArgumentCaptor.forClass(SysUser.class);
|
||||
verify(userRepository).save(userCaptor.capture());
|
||||
verify(passwordEncoder).encode("raw_password");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testDeleteUser() {
|
||||
when(userRepository.findById(1L)).thenReturn(Mono.just(testUser));
|
||||
when(userRepository.deleteById(1L)).thenReturn(Mono.empty());
|
||||
|
||||
StepVerifier.create(userService.deleteUser(1L))
|
||||
.verifyComplete();
|
||||
|
||||
verify(userRepository).deleteById(1L);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testChangePassword_Success() {
|
||||
when(userRepository.findById(1L)).thenReturn(Mono.just(testUser));
|
||||
when(passwordEncoder.matches("old_password", "encoded_password")).thenReturn(true);
|
||||
when(passwordEncoder.encode("new_password")).thenReturn("new_encoded_password");
|
||||
when(userRepository.save(any(SysUser.class))).thenReturn(Mono.just(testUser));
|
||||
|
||||
StepVerifier.create(userService.changePassword(1L, "old_password", "new_password"))
|
||||
.expectNextMatches(user -> user.getPassword().equals("new_encoded_password"))
|
||||
.verifyComplete();
|
||||
|
||||
verify(passwordEncoder).matches("old_password", "encoded_password");
|
||||
verify(passwordEncoder).encode("new_password");
|
||||
verify(userRepository).save(any(SysUser.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testChangePassword_WrongOldPassword() {
|
||||
when(userRepository.findById(1L)).thenReturn(Mono.just(testUser));
|
||||
when(passwordEncoder.matches("wrong_password", "encoded_password")).thenReturn(false);
|
||||
|
||||
StepVerifier.create(userService.changePassword(1L, "wrong_password", "new_password"))
|
||||
.expectError(RuntimeException.class)
|
||||
.verify();
|
||||
|
||||
verify(passwordEncoder).matches("wrong_password", "encoded_password");
|
||||
verify(passwordEncoder, never()).encode(anyString());
|
||||
verify(userRepository, never()).save(any(SysUser.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testExistsByUsername_True() {
|
||||
when(userRepository.findByUsername("testuser")).thenReturn(Mono.just(testUser));
|
||||
|
||||
StepVerifier.create(userService.existsByUsername("testuser"))
|
||||
.expectNext(true)
|
||||
.verifyComplete();
|
||||
|
||||
verify(userRepository).findByUsername("testuser");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testExistsByUsername_False() {
|
||||
when(userRepository.findByUsername("nonexistent")).thenReturn(Mono.empty());
|
||||
|
||||
StepVerifier.create(userService.existsByUsername("nonexistent"))
|
||||
.expectNext(false)
|
||||
.verifyComplete();
|
||||
|
||||
verify(userRepository).findByUsername("nonexistent");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testExistsByEmail_True() {
|
||||
when(userRepository.findByEmail("test@example.com")).thenReturn(Mono.just(testUser));
|
||||
|
||||
StepVerifier.create(userService.existsByEmail("test@example.com"))
|
||||
.expectNext(true)
|
||||
.verifyComplete();
|
||||
|
||||
verify(userRepository).findByEmail("test@example.com");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testExistsByEmail_False() {
|
||||
when(userRepository.findByEmail("nonexistent@example.com")).thenReturn(Mono.empty());
|
||||
|
||||
StepVerifier.create(userService.existsByEmail("nonexistent@example.com"))
|
||||
.expectNext(false)
|
||||
.verifyComplete();
|
||||
|
||||
verify(userRepository).findByEmail("nonexistent@example.com");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testLogicalDeleteUser() {
|
||||
when(userRepository.findByIdIncludingDeleted(1L)).thenReturn(Mono.just(testUser));
|
||||
when(userRepository.save(any(SysUser.class))).thenReturn(Mono.just(testUser));
|
||||
|
||||
StepVerifier.create(userService.logicalDeleteUser(1L))
|
||||
.verifyComplete();
|
||||
|
||||
ArgumentCaptor<SysUser> userCaptor = ArgumentCaptor.forClass(SysUser.class);
|
||||
verify(userRepository).save(userCaptor.capture());
|
||||
assert userCaptor.getValue().getDeletedAt() != null : "DeletedAt should be set";
|
||||
}
|
||||
|
||||
@Test
|
||||
void testLogicalDeleteUsers() {
|
||||
List<Long> ids = List.of(1L, 2L, 3L);
|
||||
when(userRepository.logicalDeleteByIds(ids)).thenReturn(Mono.empty());
|
||||
|
||||
StepVerifier.create(userService.logicalDeleteUsers(ids))
|
||||
.verifyComplete();
|
||||
|
||||
verify(userRepository).logicalDeleteByIds(ids);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testRestoreUser() {
|
||||
SysUser deletedUser = new SysUser();
|
||||
deletedUser.setId(1L);
|
||||
deletedUser.setDeletedAt(LocalDateTime.now());
|
||||
|
||||
when(userRepository.findByIdIncludingDeleted(1L)).thenReturn(Mono.just(deletedUser));
|
||||
when(userRepository.save(any(SysUser.class))).thenReturn(Mono.just(testUser));
|
||||
|
||||
StepVerifier.create(userService.restoreUser(1L))
|
||||
.verifyComplete();
|
||||
|
||||
ArgumentCaptor<SysUser> userCaptor = ArgumentCaptor.forClass(SysUser.class);
|
||||
verify(userRepository).save(userCaptor.capture());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testRestoreUsers() {
|
||||
List<Long> ids = List.of(1L, 2L, 3L);
|
||||
when(userRepository.restoreByIds(ids)).thenReturn(Mono.empty());
|
||||
|
||||
StepVerifier.create(userService.restoreUsers(ids))
|
||||
.verifyComplete();
|
||||
|
||||
verify(userRepository).restoreByIds(ids);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCreateUser_WithNullStatus() {
|
||||
SysUser newUser = new SysUser();
|
||||
newUser.setUsername("newuser");
|
||||
newUser.setPassword("raw_password");
|
||||
newUser.setEmail("new@example.com");
|
||||
newUser.setStatus(null);
|
||||
|
||||
when(passwordEncoder.encode("raw_password")).thenReturn("encoded_password");
|
||||
when(userRepository.save(any(SysUser.class))).thenReturn(Mono.just(testUser));
|
||||
|
||||
StepVerifier.create(userService.createUser(newUser))
|
||||
.expectNextMatches(user -> user.getPassword().equals("encoded_password") &&
|
||||
user.getStatus().equals(StatusConstants.ENABLED) &&
|
||||
user.getCreatedAt() != null)
|
||||
.verifyComplete();
|
||||
|
||||
verify(passwordEncoder).encode("raw_password");
|
||||
verify(userRepository).save(any(SysUser.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCreateUser_WithExistingStatus() {
|
||||
SysUser newUser = new SysUser();
|
||||
newUser.setUsername("newuser");
|
||||
newUser.setPassword("raw_password");
|
||||
newUser.setEmail("new@example.com");
|
||||
newUser.setStatus(StatusConstants.DISABLED);
|
||||
|
||||
SysUser savedUser = new SysUser();
|
||||
savedUser.setId(1L);
|
||||
savedUser.setUsername("newuser");
|
||||
savedUser.setPassword("encoded_password");
|
||||
savedUser.setEmail("new@example.com");
|
||||
savedUser.setStatus(StatusConstants.DISABLED);
|
||||
savedUser.setCreatedAt(LocalDateTime.now());
|
||||
|
||||
when(passwordEncoder.encode("raw_password")).thenReturn("encoded_password");
|
||||
when(userRepository.save(any(SysUser.class))).thenReturn(Mono.just(savedUser));
|
||||
|
||||
StepVerifier.create(userService.createUser(newUser))
|
||||
.expectNextMatches(user -> user.getPassword().equals("encoded_password") &&
|
||||
user.getStatus().equals(StatusConstants.DISABLED) &&
|
||||
user.getCreatedAt() != null)
|
||||
.verifyComplete();
|
||||
|
||||
verify(passwordEncoder).encode("raw_password");
|
||||
verify(userRepository).save(any(SysUser.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testDeleteUser_UserNotFound() {
|
||||
when(userRepository.findById(999L)).thenReturn(Mono.empty());
|
||||
|
||||
StepVerifier.create(userService.deleteUser(999L))
|
||||
.expectError(RuntimeException.class)
|
||||
.verify();
|
||||
|
||||
verify(userRepository).findById(999L);
|
||||
verify(userRepository, never()).deleteById(anyLong());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFindUsersByPage_WithKeyword() {
|
||||
PageRequest pageRequest = new PageRequest();
|
||||
pageRequest.setPage(0);
|
||||
pageRequest.setSize(10);
|
||||
pageRequest.setKeyword("test");
|
||||
|
||||
PageResponse<SysUser> pageResponse = new PageResponse<>();
|
||||
pageResponse.setContent(List.of(testUser));
|
||||
pageResponse.setTotalElements(1L);
|
||||
|
||||
when(userRepository.findByQueryWithPagination(isNull(), eq(pageRequest)))
|
||||
.thenReturn(Mono.just(pageResponse));
|
||||
|
||||
StepVerifier.create(userService.findUsersByPage(pageRequest))
|
||||
.expectNextMatches(response -> response.getTotalElements() == 1L)
|
||||
.verifyComplete();
|
||||
|
||||
verify(userRepository).findByQueryWithPagination(isNull(), eq(pageRequest));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFindUsersByPage_WithoutKeyword() {
|
||||
PageRequest pageRequest = new PageRequest();
|
||||
pageRequest.setPage(0);
|
||||
pageRequest.setSize(10);
|
||||
|
||||
PageResponse<SysUser> pageResponse = new PageResponse<>();
|
||||
pageResponse.setContent(List.of(testUser));
|
||||
pageResponse.setTotalElements(1L);
|
||||
|
||||
when(userRepository.findByQueryWithPagination(isNull(), eq(pageRequest)))
|
||||
.thenReturn(Mono.just(pageResponse));
|
||||
|
||||
StepVerifier.create(userService.findUsersByPage(pageRequest))
|
||||
.expectNextMatches(response -> response.getTotalElements() == 1L)
|
||||
.verifyComplete();
|
||||
|
||||
verify(userRepository).findByQueryWithPagination(isNull(), eq(pageRequest));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFindUsersByPage_WithEmptyKeyword() {
|
||||
PageRequest pageRequest = new PageRequest();
|
||||
pageRequest.setPage(0);
|
||||
pageRequest.setSize(10);
|
||||
pageRequest.setKeyword("");
|
||||
|
||||
PageResponse<SysUser> pageResponse = new PageResponse<>();
|
||||
pageResponse.setContent(List.of(testUser));
|
||||
pageResponse.setTotalElements(1L);
|
||||
|
||||
when(userRepository.findByQueryWithPagination(isNull(), eq(pageRequest)))
|
||||
.thenReturn(Mono.just(pageResponse));
|
||||
|
||||
StepVerifier.create(userService.findUsersByPage(pageRequest))
|
||||
.expectNextMatches(response -> response.getTotalElements() == 1L)
|
||||
.verifyComplete();
|
||||
|
||||
verify(userRepository).findByQueryWithPagination(isNull(), eq(pageRequest));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testUpdateUserWithCommand_WithAllFields() {
|
||||
SysUser existingUser = new SysUser();
|
||||
existingUser.setId(1L);
|
||||
existingUser.setUsername("olduser");
|
||||
existingUser.setEmail("old@example.com");
|
||||
existingUser.setRoleId(1L);
|
||||
existingUser.setStatus(StatusConstants.ENABLED);
|
||||
|
||||
when(userRepository.findById(1L)).thenReturn(Mono.just(existingUser));
|
||||
when(userRepository.save(any(SysUser.class))).thenReturn(Mono.just(testUser));
|
||||
|
||||
cn.novalon.manage.sys.core.command.UpdateUserCommand command = cn.novalon.manage.sys.core.command.UpdateUserCommand
|
||||
.of(
|
||||
1L, "newuser", "newpass", "new@example.com", 2L,
|
||||
StatusConstants.DISABLED);
|
||||
|
||||
StepVerifier.create(userService.updateUser(command))
|
||||
.expectNextMatches(user -> user.getUpdatedAt() != null)
|
||||
.verifyComplete();
|
||||
|
||||
verify(userRepository).findById(1L);
|
||||
verify(userRepository).save(any(SysUser.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testUpdateUserWithCommand_WithPartialFields() {
|
||||
SysUser existingUser = new SysUser();
|
||||
existingUser.setId(1L);
|
||||
existingUser.setUsername("olduser");
|
||||
existingUser.setEmail("old@example.com");
|
||||
existingUser.setRoleId(1L);
|
||||
existingUser.setStatus(StatusConstants.ENABLED);
|
||||
|
||||
when(userRepository.findById(1L)).thenReturn(Mono.just(existingUser));
|
||||
when(userRepository.save(any(SysUser.class))).thenReturn(Mono.just(testUser));
|
||||
|
||||
cn.novalon.manage.sys.core.command.UpdateUserCommand command = cn.novalon.manage.sys.core.command.UpdateUserCommand
|
||||
.of(
|
||||
1L, null, null, null, null, null);
|
||||
|
||||
StepVerifier.create(userService.updateUser(command))
|
||||
.expectNextMatches(user -> user.getUpdatedAt() != null)
|
||||
.verifyComplete();
|
||||
|
||||
verify(userRepository).findById(1L);
|
||||
verify(userRepository).save(any(SysUser.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCreateUserWithCommand_Success() {
|
||||
cn.novalon.manage.sys.core.command.CreateUserCommand command = cn.novalon.manage.sys.core.command.CreateUserCommand
|
||||
.of(
|
||||
"newuser",
|
||||
"Password123!",
|
||||
"newuser@example.com",
|
||||
null, null, 1L,
|
||||
StatusConstants.ENABLED);
|
||||
|
||||
when(passwordEncoder.encode("Password123!")).thenReturn("encoded_password");
|
||||
when(userRepository.save(any(SysUser.class))).thenAnswer(invocation -> {
|
||||
SysUser savedUser = invocation.getArgument(0);
|
||||
savedUser.setId(1L);
|
||||
return Mono.just(savedUser);
|
||||
});
|
||||
|
||||
StepVerifier.create(userService.createUser(command))
|
||||
.expectNextMatches(user -> user.getUsername().equals("newuser") &&
|
||||
user.getPassword().equals("encoded_password") &&
|
||||
user.getEmail().equals("newuser@example.com") &&
|
||||
user.getRoleId().equals(1L) &&
|
||||
user.getStatus().equals(StatusConstants.ENABLED) &&
|
||||
user.getCreatedAt() != null)
|
||||
.verifyComplete();
|
||||
|
||||
verify(passwordEncoder).encode("Password123!");
|
||||
verify(userRepository).save(any(SysUser.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCreateUserWithCommand_WithNullStatus() {
|
||||
cn.novalon.manage.sys.core.command.CreateUserCommand command = cn.novalon.manage.sys.core.command.CreateUserCommand
|
||||
.of(
|
||||
"newuser",
|
||||
"Password123!",
|
||||
"newuser@example.com",
|
||||
null, null, 1L,
|
||||
null);
|
||||
|
||||
when(passwordEncoder.encode("Password123!")).thenReturn("encoded_password");
|
||||
when(userRepository.save(any(SysUser.class))).thenAnswer(invocation -> {
|
||||
SysUser savedUser = invocation.getArgument(0);
|
||||
savedUser.setId(1L);
|
||||
return Mono.just(savedUser);
|
||||
});
|
||||
|
||||
StepVerifier.create(userService.createUser(command))
|
||||
.expectNextMatches(user -> user.getStatus().equals(StatusConstants.ENABLED))
|
||||
.verifyComplete();
|
||||
|
||||
verify(userRepository).save(any(SysUser.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testUpdateUserWithCommand_AllFields() {
|
||||
SysUser existingUser = new SysUser();
|
||||
existingUser.setId(1L);
|
||||
existingUser.setUsername("olduser");
|
||||
existingUser.setEmail("old@example.com");
|
||||
existingUser.setRoleId(1L);
|
||||
existingUser.setStatus(StatusConstants.ENABLED);
|
||||
|
||||
cn.novalon.manage.sys.core.command.UpdateUserCommand command = cn.novalon.manage.sys.core.command.UpdateUserCommand
|
||||
.of(
|
||||
1L, "newuser", "NewPassword123!", "new@example.com", 2L,
|
||||
StatusConstants.DISABLED);
|
||||
|
||||
when(userRepository.findById(1L)).thenReturn(Mono.just(existingUser));
|
||||
when(passwordEncoder.encode("NewPassword123!")).thenReturn("encoded_newpassword");
|
||||
when(userRepository.save(any(SysUser.class))).thenAnswer(invocation -> {
|
||||
SysUser savedUser = invocation.getArgument(0);
|
||||
return Mono.just(savedUser);
|
||||
});
|
||||
|
||||
StepVerifier.create(userService.updateUser(command))
|
||||
.expectNextMatches(user -> user.getUsername().equals("newuser") &&
|
||||
user.getPassword().equals("encoded_newpassword") &&
|
||||
user.getEmail().equals("new@example.com") &&
|
||||
user.getRoleId().equals(2L) &&
|
||||
user.getStatus().equals(StatusConstants.DISABLED) &&
|
||||
user.getUpdatedAt() != null)
|
||||
.verifyComplete();
|
||||
|
||||
verify(userRepository).findById(1L);
|
||||
verify(passwordEncoder).encode("NewPassword123!");
|
||||
verify(userRepository).save(any(SysUser.class));
|
||||
}
|
||||
@Mock
|
||||
private ISysUserRepository userRepository;
|
||||
|
||||
@Mock
|
||||
private ISysRoleRepository roleRepository;
|
||||
|
||||
@Mock
|
||||
private IUserRoleRepository userRoleRepository;
|
||||
|
||||
@Mock
|
||||
private PasswordEncoder passwordEncoder;
|
||||
|
||||
private SysUserService userService;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
userService = new SysUserService(userRepository, roleRepository, userRoleRepository, passwordEncoder);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFindById() {
|
||||
SysUser user = new SysUser();
|
||||
user.setId(1L);
|
||||
user.setUsername("testuser");
|
||||
user.setEmail("test@example.com");
|
||||
|
||||
when(userRepository.findById(1L)).thenReturn(Mono.just(user));
|
||||
|
||||
StepVerifier.create(userService.findById(1L))
|
||||
.expectNextMatches(u -> u.getId().equals(1L) && u.getUsername().equals("testuser"))
|
||||
.verifyComplete();
|
||||
|
||||
verify(userRepository, times(1)).findById(1L);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFindByIdNotFound() {
|
||||
when(userRepository.findById(999L)).thenReturn(Mono.empty());
|
||||
|
||||
StepVerifier.create(userService.findById(999L))
|
||||
.verifyComplete();
|
||||
|
||||
verify(userRepository, times(1)).findById(999L);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFindAll() {
|
||||
SysUser user1 = new SysUser();
|
||||
user1.setId(1L);
|
||||
user1.setUsername("user1");
|
||||
|
||||
SysUser user2 = new SysUser();
|
||||
user2.setId(2L);
|
||||
user2.setUsername("user2");
|
||||
|
||||
when(userRepository.findByDeletedAtIsNull()).thenReturn(Flux.just(user1, user2));
|
||||
|
||||
StepVerifier.create(userService.findAll(false))
|
||||
.expectNext(user1)
|
||||
.expectNext(user2)
|
||||
.verifyComplete();
|
||||
|
||||
verify(userRepository, times(1)).findByDeletedAtIsNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCreateUser() {
|
||||
SysUser user = new SysUser();
|
||||
user.setUsername("newuser");
|
||||
user.setPassword("plainPassword");
|
||||
user.setEmail("newuser@example.com");
|
||||
|
||||
when(passwordEncoder.encode(anyString())).thenReturn("$2b$12$encodedPassword");
|
||||
when(userRepository.save(any(SysUser.class))).thenAnswer(invocation -> {
|
||||
SysUser savedUser = invocation.getArgument(0);
|
||||
savedUser.setId(1L);
|
||||
return Mono.just(savedUser);
|
||||
});
|
||||
|
||||
StepVerifier.create(userService.createUser(user))
|
||||
.expectNextMatches(savedUser ->
|
||||
savedUser.getId().equals(1L) &&
|
||||
savedUser.getPassword().equals("$2b$12$encodedPassword") &&
|
||||
savedUser.getStatus().equals(StatusConstants.ENABLED)
|
||||
)
|
||||
.verifyComplete();
|
||||
|
||||
verify(passwordEncoder, times(1)).encode("plainPassword");
|
||||
verify(userRepository, times(1)).save(any(SysUser.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCreateUserWithCommand() {
|
||||
CreateUserCommand command = mock(CreateUserCommand.class);
|
||||
when(command.username()).thenReturn(mock(cn.novalon.manage.sys.primitive.Username.class));
|
||||
when(command.password()).thenReturn(mock(cn.novalon.manage.sys.primitive.Password.class));
|
||||
when(command.email()).thenReturn(mock(cn.novalon.manage.sys.primitive.Email.class));
|
||||
when(command.username().getValue()).thenReturn("testuser");
|
||||
when(command.password().getValue()).thenReturn("password123");
|
||||
when(command.email().getValue()).thenReturn("test@example.com");
|
||||
when(command.nickname()).thenReturn("Test User");
|
||||
when(command.phone()).thenReturn("13800138000");
|
||||
when(command.roleId()).thenReturn(1L);
|
||||
when(command.status()).thenReturn(null);
|
||||
|
||||
when(passwordEncoder.encode(anyString())).thenReturn("$2b$12$encodedPassword");
|
||||
when(userRepository.save(any(SysUser.class))).thenAnswer(invocation -> {
|
||||
SysUser savedUser = invocation.getArgument(0);
|
||||
savedUser.setId(1L);
|
||||
return Mono.just(savedUser);
|
||||
});
|
||||
|
||||
StepVerifier.create(userService.createUser(command))
|
||||
.expectNextMatches(savedUser ->
|
||||
savedUser.getUsername().equals("testuser") &&
|
||||
savedUser.getPassword().equals("$2b$12$encodedPassword") &&
|
||||
savedUser.getEmail().equals("test@example.com")
|
||||
)
|
||||
.verifyComplete();
|
||||
|
||||
verify(passwordEncoder, times(1)).encode("password123");
|
||||
verify(userRepository, times(1)).save(any(SysUser.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testUpdateUser() {
|
||||
SysUser user = new SysUser();
|
||||
user.setId(1L);
|
||||
user.setUsername("testuser");
|
||||
user.setEmail("updated@example.com");
|
||||
|
||||
when(userRepository.save(any(SysUser.class))).thenReturn(Mono.just(user));
|
||||
|
||||
StepVerifier.create(userService.updateUser(user))
|
||||
.expectNextMatches(updatedUser ->
|
||||
updatedUser.getId().equals(1L) &&
|
||||
updatedUser.getEmail().equals("updated@example.com")
|
||||
)
|
||||
.verifyComplete();
|
||||
|
||||
verify(userRepository, times(1)).save(any(SysUser.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testDeleteUser() {
|
||||
SysUser user = new SysUser();
|
||||
user.setId(1L);
|
||||
user.setUsername("testuser");
|
||||
|
||||
when(userRepository.findById(1L)).thenReturn(Mono.just(user));
|
||||
when(userRoleRepository.deleteByUserId(1L)).thenReturn(Mono.empty());
|
||||
when(userRepository.deleteById(1L)).thenReturn(Mono.empty());
|
||||
|
||||
StepVerifier.create(userService.deleteUser(1L))
|
||||
.verifyComplete();
|
||||
|
||||
verify(userRepository, times(1)).findById(1L);
|
||||
verify(userRoleRepository, times(1)).deleteByUserId(1L);
|
||||
verify(userRepository, times(1)).deleteById(1L);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testDeleteUserNotFound() {
|
||||
when(userRepository.findById(999L)).thenReturn(Mono.empty());
|
||||
|
||||
StepVerifier.create(userService.deleteUser(999L))
|
||||
.expectErrorMatches(error -> error instanceof RuntimeException &&
|
||||
error.getMessage().equals("User not found"))
|
||||
.verify();
|
||||
|
||||
verify(userRepository, times(1)).findById(999L);
|
||||
verify(userRoleRepository, never()).deleteByUserId(anyLong());
|
||||
verify(userRepository, never()).deleteById(anyLong());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testChangePassword() {
|
||||
SysUser user = new SysUser();
|
||||
user.setId(1L);
|
||||
user.setUsername("testuser");
|
||||
user.setPassword("$2b$12$oldPassword");
|
||||
|
||||
when(userRepository.findById(1L)).thenReturn(Mono.just(user));
|
||||
when(passwordEncoder.matches("oldPassword", "$2b$12$oldPassword")).thenReturn(true);
|
||||
when(passwordEncoder.encode("newPassword")).thenReturn("$2b$12$newPassword");
|
||||
when(userRepository.save(any(SysUser.class))).thenAnswer(invocation -> Mono.just(invocation.getArgument(0)));
|
||||
|
||||
StepVerifier.create(userService.changePassword(1L, "oldPassword", "newPassword"))
|
||||
.expectNextMatches(updatedUser ->
|
||||
updatedUser.getPassword().equals("$2b$12$newPassword")
|
||||
)
|
||||
.verifyComplete();
|
||||
|
||||
verify(passwordEncoder, times(1)).matches("oldPassword", "$2b$12$oldPassword");
|
||||
verify(passwordEncoder, times(1)).encode("newPassword");
|
||||
verify(userRepository, times(1)).save(any(SysUser.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testChangePasswordIncorrectOldPassword() {
|
||||
SysUser user = new SysUser();
|
||||
user.setId(1L);
|
||||
user.setUsername("testuser");
|
||||
user.setPassword("$2b$12$oldPassword");
|
||||
|
||||
when(userRepository.findById(1L)).thenReturn(Mono.just(user));
|
||||
when(passwordEncoder.matches("wrongPassword", "$2b$12$oldPassword")).thenReturn(false);
|
||||
|
||||
StepVerifier.create(userService.changePassword(1L, "wrongPassword", "newPassword"))
|
||||
.expectErrorMatches(error -> error instanceof RuntimeException &&
|
||||
error.getMessage().equals("旧密码不正确"))
|
||||
.verify();
|
||||
|
||||
verify(passwordEncoder, times(1)).matches("wrongPassword", "$2b$12$oldPassword");
|
||||
verify(passwordEncoder, never()).encode(anyString());
|
||||
verify(userRepository, never()).save(any(SysUser.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testExistsByUsername() {
|
||||
when(userRepository.findByUsername("existinguser")).thenReturn(Mono.just(new SysUser()));
|
||||
when(userRepository.findByUsername("nonexistinguser")).thenReturn(Mono.empty());
|
||||
|
||||
StepVerifier.create(userService.existsByUsername("existinguser"))
|
||||
.expectNext(true)
|
||||
.verifyComplete();
|
||||
|
||||
StepVerifier.create(userService.existsByUsername("nonexistinguser"))
|
||||
.expectNext(false)
|
||||
.verifyComplete();
|
||||
|
||||
verify(userRepository, times(1)).findByUsername("existinguser");
|
||||
verify(userRepository, times(1)).findByUsername("nonexistinguser");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testAssignRolesToUser() {
|
||||
Long userId = 1L;
|
||||
java.util.List<Long> roleIds = Arrays.asList(1L, 2L);
|
||||
|
||||
when(userRoleRepository.deleteByUserId(userId)).thenReturn(Mono.empty());
|
||||
when(userRoleRepository.save(any(UserRole.class))).thenReturn(Mono.just(new UserRole()));
|
||||
|
||||
StepVerifier.create(userService.assignRolesToUser(userId, roleIds))
|
||||
.verifyComplete();
|
||||
|
||||
verify(userRoleRepository, times(1)).deleteByUserId(userId);
|
||||
verify(userRoleRepository, times(2)).save(any(UserRole.class));
|
||||
}
|
||||
}
|
||||
|
||||
-210
@@ -1,210 +0,0 @@
|
||||
package cn.novalon.manage.sys.interceptor;
|
||||
|
||||
import cn.novalon.manage.sys.core.domain.OperationLog;
|
||||
import cn.novalon.manage.sys.core.service.IOperationLogService;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.mock.http.server.reactive.MockServerHttpRequest;
|
||||
import org.springframework.mock.web.server.MockServerWebExchange;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import org.springframework.web.server.WebFilterChain;
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.test.StepVerifier;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class OperationLogFilterTest {
|
||||
|
||||
@Mock
|
||||
private IOperationLogService logService;
|
||||
|
||||
@Mock
|
||||
private WebFilterChain chain;
|
||||
|
||||
@Mock
|
||||
private ObjectMapper objectMapper;
|
||||
|
||||
private OperationLogFilter filter;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
filter = new OperationLogFilter(logService, objectMapper);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFilter_SkipAuthEndpoints() {
|
||||
MockServerHttpRequest request = MockServerHttpRequest.get("/api/auth/login").build();
|
||||
ServerWebExchange exchange = MockServerWebExchange.from(request);
|
||||
|
||||
when(chain.filter(exchange)).thenReturn(Mono.empty());
|
||||
|
||||
StepVerifier.create(filter.filter(exchange, chain))
|
||||
.verifyComplete();
|
||||
|
||||
verify(chain).filter(exchange);
|
||||
verify(logService, never()).save(any(OperationLog.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFilter_RecordSuccessLog() {
|
||||
MockServerHttpRequest request = MockServerHttpRequest.get("/api/users")
|
||||
.remoteAddress(new InetSocketAddress("127.0.0.1", 8080))
|
||||
.build();
|
||||
ServerWebExchange exchange = MockServerWebExchange.from(request);
|
||||
|
||||
when(chain.filter(exchange)).thenReturn(Mono.empty());
|
||||
when(logService.save(any(OperationLog.class))).thenReturn(Mono.just(new OperationLog()));
|
||||
|
||||
StepVerifier.create(filter.filter(exchange, chain))
|
||||
.verifyComplete();
|
||||
|
||||
verify(chain).filter(exchange);
|
||||
verify(logService).save(any(OperationLog.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFilter_RecordErrorLog() {
|
||||
MockServerHttpRequest request = MockServerHttpRequest.get("/api/users")
|
||||
.remoteAddress(new InetSocketAddress("127.0.0.1", 8080))
|
||||
.build();
|
||||
ServerWebExchange exchange = MockServerWebExchange.from(request);
|
||||
|
||||
RuntimeException error = new RuntimeException("Test error");
|
||||
when(chain.filter(exchange)).thenReturn(Mono.error(error));
|
||||
when(logService.save(any(OperationLog.class))).thenReturn(Mono.just(new OperationLog()));
|
||||
|
||||
StepVerifier.create(filter.filter(exchange, chain))
|
||||
.expectError(RuntimeException.class)
|
||||
.verify();
|
||||
|
||||
verify(chain).filter(exchange);
|
||||
verify(logService).save(any(OperationLog.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFilter_WithXForwardedForHeader() {
|
||||
MockServerHttpRequest request = MockServerHttpRequest.get("/api/users")
|
||||
.header("X-Forwarded-For", "192.168.1.1")
|
||||
.build();
|
||||
ServerWebExchange exchange = MockServerWebExchange.from(request);
|
||||
|
||||
when(chain.filter(exchange)).thenReturn(Mono.empty());
|
||||
when(logService.save(any(OperationLog.class))).thenReturn(Mono.just(new OperationLog()));
|
||||
|
||||
StepVerifier.create(filter.filter(exchange, chain))
|
||||
.verifyComplete();
|
||||
|
||||
verify(logService).save(argThat(log -> "192.168.1.1".equals(log.getIp())));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFilter_WithXRealIPHeader() {
|
||||
MockServerHttpRequest request = MockServerHttpRequest.get("/api/users")
|
||||
.header("X-Real-IP", "10.0.0.1")
|
||||
.build();
|
||||
ServerWebExchange exchange = MockServerWebExchange.from(request);
|
||||
|
||||
when(chain.filter(exchange)).thenReturn(Mono.empty());
|
||||
when(logService.save(any(OperationLog.class))).thenReturn(Mono.just(new OperationLog()));
|
||||
|
||||
StepVerifier.create(filter.filter(exchange, chain))
|
||||
.verifyComplete();
|
||||
|
||||
verify(logService).save(argThat(log -> "10.0.0.1".equals(log.getIp())));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFilter_WithMultipleIPsInXForwardedFor() {
|
||||
MockServerHttpRequest request = MockServerHttpRequest.get("/api/users")
|
||||
.header("X-Forwarded-For", "192.168.1.1, 10.0.0.1")
|
||||
.build();
|
||||
ServerWebExchange exchange = MockServerWebExchange.from(request);
|
||||
|
||||
when(chain.filter(exchange)).thenReturn(Mono.empty());
|
||||
when(logService.save(any(OperationLog.class))).thenReturn(Mono.just(new OperationLog()));
|
||||
|
||||
StepVerifier.create(filter.filter(exchange, chain))
|
||||
.verifyComplete();
|
||||
|
||||
verify(logService).save(argThat(log -> "192.168.1.1".equals(log.getIp())));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFilter_WithUnknownHeader() {
|
||||
MockServerHttpRequest request = MockServerHttpRequest.get("/api/users")
|
||||
.header("X-Forwarded-For", "unknown")
|
||||
.build();
|
||||
ServerWebExchange exchange = MockServerWebExchange.from(request);
|
||||
|
||||
when(chain.filter(exchange)).thenReturn(Mono.empty());
|
||||
when(logService.save(any(OperationLog.class))).thenReturn(Mono.just(new OperationLog()));
|
||||
|
||||
StepVerifier.create(filter.filter(exchange, chain))
|
||||
.verifyComplete();
|
||||
|
||||
verify(logService).save(any(OperationLog.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFilter_DifferentHttpMethods() {
|
||||
HttpMethod[] methods = {HttpMethod.GET, HttpMethod.POST, HttpMethod.PUT, HttpMethod.DELETE, HttpMethod.PATCH};
|
||||
|
||||
for (HttpMethod method : methods) {
|
||||
MockServerHttpRequest request = MockServerHttpRequest.method(method, "/api/users")
|
||||
.remoteAddress(new InetSocketAddress("127.0.0.1", 8080))
|
||||
.build();
|
||||
ServerWebExchange exchange = MockServerWebExchange.from(request);
|
||||
|
||||
when(chain.filter(exchange)).thenReturn(Mono.empty());
|
||||
when(logService.save(any(OperationLog.class))).thenReturn(Mono.just(new OperationLog()));
|
||||
|
||||
StepVerifier.create(filter.filter(exchange, chain))
|
||||
.verifyComplete();
|
||||
|
||||
verify(logService).save(argThat(log -> method.name().equals(log.getMethod())));
|
||||
reset(logService, chain);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFilter_WithQueryParams() {
|
||||
MockServerHttpRequest request = MockServerHttpRequest.get("/api/users?page=1&size=10")
|
||||
.remoteAddress(new InetSocketAddress("127.0.0.1", 8080))
|
||||
.build();
|
||||
ServerWebExchange exchange = MockServerWebExchange.from(request);
|
||||
|
||||
when(chain.filter(exchange)).thenReturn(Mono.empty());
|
||||
when(logService.save(any(OperationLog.class))).thenReturn(Mono.just(new OperationLog()));
|
||||
|
||||
StepVerifier.create(filter.filter(exchange, chain))
|
||||
.verifyComplete();
|
||||
|
||||
verify(logService).save(argThat(log -> log.getParams() != null && !log.getParams().isEmpty()));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFilter_LogSaveError() {
|
||||
MockServerHttpRequest request = MockServerHttpRequest.get("/api/users")
|
||||
.remoteAddress(new InetSocketAddress("127.0.0.1", 8080))
|
||||
.build();
|
||||
ServerWebExchange exchange = MockServerWebExchange.from(request);
|
||||
|
||||
when(chain.filter(exchange)).thenReturn(Mono.empty());
|
||||
when(logService.save(any(OperationLog.class))).thenReturn(Mono.error(new RuntimeException("Save failed")));
|
||||
|
||||
StepVerifier.create(filter.filter(exchange, chain))
|
||||
.verifyComplete();
|
||||
|
||||
verify(chain).filter(exchange);
|
||||
verify(logService).save(any(OperationLog.class));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user