| package edu.bjtu.groupone.backend; |
| |
| import edu.bjtu.groupone.backend.mapper.UserMapper; |
| import edu.bjtu.groupone.backend.utils.EmailUtil; |
| import edu.bjtu.groupone.backend.service.impl.UserServImpl; |
| import edu.bjtu.groupone.backend.model.User; |
| import org.junit.jupiter.api.BeforeEach; |
| import org.junit.jupiter.api.Test; |
| import org.junit.jupiter.api.extension.ExtendWith; |
| import org.mockito.InjectMocks; |
| import org.mockito.Mock; |
| import org.mockito.junit.jupiter.MockitoExtension; |
| |
| import java.lang.reflect.Field; |
| |
| import static org.assertj.core.api.Assertions.*; |
| import static org.mockito.Mockito.*; |
| |
| /** |
| * 单元测试 UserServImpl 的核心逻辑:登录、发/验注册码、发/验重置码、重置密码。 |
| */ |
| @ExtendWith(MockitoExtension.class) |
| public class UserServImplTest { |
| |
| @Mock |
| private UserMapper userMapper; |
| |
| @Mock |
| private EmailUtil emailUtil; |
| |
| @InjectMocks |
| private UserServImpl userService; |
| |
| @BeforeEach |
| void clearCaches() throws Exception { |
| clearMap("emailCodes"); |
| clearMap("resetCodes"); |
| } |
| |
| @Test |
| public void login_shouldReturnUser_whenCredentialsMatch() { |
| User in = new User(); |
| in.setEmail("a@b.com"); |
| in.setPassword("pwd"); |
| User out = new User(); |
| out.setUserId(1); |
| out.setUsername("alice"); |
| out.setEmail("a@b.com"); |
| when(userMapper.login(in)).thenReturn(out); |
| |
| User result = userService.login(in); |
| assertThat(result).isSameAs(out); |
| verify(userMapper, times(1)).login(in); |
| } |
| |
| @Test |
| public void sendVerification_and_verifyCode_workCorrectly() throws Exception { |
| String email = "test@x.com"; |
| userService.sendVerificationCode(email); |
| verify(emailUtil).sendVerificationEmail(eq(email), anyString()); |
| |
| String stored = readMap("emailCodes", email); |
| String code = stored.split("\\|")[0]; |
| assertThat(userService.verifyCode(email, code)).isTrue(); |
| assertThat(userService.verifyCode(email, "000000")).isFalse(); |
| |
| // 模拟过期 |
| patchExpiry("emailCodes", email, -1000L); |
| assertThat(userService.verifyCode(email, code)).isFalse(); |
| } |
| |
| @Test |
| public void sendResetCode_and_resetPassword_workCorrectly() throws Exception { |
| String email = "reset@x.com"; |
| when(userMapper.selectByEmail(email)).thenReturn(null); |
| assertThatThrownBy(() -> userService.sendResetCode(email)) |
| .isInstanceOf(IllegalArgumentException.class); |
| |
| User u = new User(); |
| u.setEmail(email); |
| when(userMapper.selectByEmail(email)).thenReturn(u); |
| |
| userService.sendResetCode(email); |
| verify(emailUtil).sendVerificationEmail(eq(email), anyString()); |
| String stored = readMap("resetCodes", email); |
| String code = stored.split("\\|")[0]; |
| |
| when(userMapper.updatePasswordByEmail(email, "newpwd")).thenReturn(1); |
| assertThat(userService.resetPassword(email, code, "newpwd")).isTrue(); |
| assertThat(userService.resetPassword(email, code, "abc")).isFalse(); |
| |
| userService.sendResetCode(email); |
| String stored2 = readMap("resetCodes", email); |
| String code2 = stored2.split("\\|")[0]; |
| patchExpiry("resetCodes", email, -2000L); |
| assertThat(userService.resetPassword(email, code2, "pw")).isFalse(); |
| } |
| |
| // --- 反射辅助方法 --- |
| @SuppressWarnings("unchecked") |
| private void clearMap(String fieldName) throws Exception { |
| Field f = UserServImpl.class.getDeclaredField(fieldName); |
| f.setAccessible(true); |
| ((java.util.Map<String, String>)f.get(userService)).clear(); |
| } |
| |
| @SuppressWarnings("unchecked") |
| private String readMap(String fieldName, String key) throws Exception { |
| Field f = UserServImpl.class.getDeclaredField(fieldName); |
| f.setAccessible(true); |
| return ((java.util.Map<String, String>)f.get(userService)).get(key); |
| } |
| |
| @SuppressWarnings("unchecked") |
| private void patchExpiry(String fieldName, String key, long offsetMs) throws Exception { |
| String combined = readMap(fieldName, key); |
| String code = combined.split("\\|")[0]; |
| long expire = System.currentTimeMillis() + offsetMs; |
| String updated = code + "|" + expire; |
| Field f = UserServImpl.class.getDeclaredField(fieldName); |
| f.setAccessible(true); |
| ((java.util.Map<String, String>)f.get(userService)).put(key, updated); |
| } |
| } |