blob: ab5a3548458da932998cd9a26ce44d1c8ed01371 [file] [log] [blame]
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.domain.entity.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);
}
}