✅ 修正自动建档测试的 selectOne 桩,恢复按 user_id 反查的可证伪性

This commit is contained in:
2026-10-23 17:17:48 +08:00
parent 77144f4e68
commit eed7d3c4d8
@@ -29,6 +29,7 @@ import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.mockStatic;
import static org.mockito.Mockito.never;
@@ -78,8 +79,9 @@ class DriverEnsureProfileTest {
@Test
@DisplayName("无账号档案、无同号档案:按占位值新建,created=true")
void createsPlaceholderProfile() {
// 第一次按 user_id 查、第二次按手机号查,都没有
when(driverMapper.selectList(any())).thenReturn(Collections.emptyList(), Collections.emptyList());
// 按 user_id 查(getOne → selectOne)与按手机号查(selectList)都没有
stubUserLookup();
when(driverMapper.selectList(any())).thenReturn(Collections.emptyList());
when(driverMapper.insert(any(Driver.class))).thenAnswer(invocation -> {
Driver inserted = invocation.getArgument(0);
inserted.setId(NEW_DRIVER_ID);
@@ -118,7 +120,8 @@ class DriverEnsureProfileTest {
@DisplayName("命中同号未绑定的档案:绑定并留痕,patch 必须带上 driving_vehicle 原值")
void bindsExistingProfileAndKeepsDrivingVehicle() {
Driver existing = driver(DRIVER_ID, null, PLATE);
when(driverMapper.selectList(any())).thenReturn(Collections.emptyList(), List.of(existing));
stubUserLookup();
when(driverMapper.selectList(any())).thenReturn(List.of(existing));
when(driverMapper.selectById(DRIVER_ID)).thenReturn(existing);
when(driverMapper.updateById(any(Driver.class))).thenReturn(1);
@@ -146,7 +149,7 @@ class DriverEnsureProfileTest {
@Test
@DisplayName("按 user_id 命中:直接返回该档案,不新建、不改手机号")
void returnsExistingProfileForRepeatLogin() {
when(driverMapper.selectList(any())).thenReturn(List.of(driver(DRIVER_ID, MP_USER_ID, PLATE)));
stubUserLookup(driver(DRIVER_ID, MP_USER_ID, PLATE));
DriverEnsureProfileVO result = service.ensureProfile(TENANT_ID, MP_USER_ID, MOBILE);
@@ -162,10 +165,8 @@ class DriverEnsureProfileTest {
@DisplayName("并发重复建档撞唯一键:重查后按已存在的档案返回,不把异常抛给登录方")
void toleratesConcurrentInsert() {
Driver concurrent = driver(DRIVER_ID, MP_USER_ID, PLATE);
when(driverMapper.selectList(any())).thenReturn(
Collections.emptyList(),
Collections.emptyList(),
List.of(concurrent));
stubUserLookup(null, concurrent);
when(driverMapper.selectList(any())).thenReturn(Collections.emptyList());
when(driverMapper.insert(any(Driver.class))).thenThrow(new DuplicateKeyException("uk_transport_driver_user"));
DriverEnsureProfileVO result = service.ensureProfile(TENANT_ID, MP_USER_ID, MOBILE);
@@ -180,8 +181,8 @@ class DriverEnsureProfileTest {
@Test
@DisplayName("同手机号多条档案:拒绝绑定也不新建,返回可读原因")
void rejectsMultipleProfilesWithSameMobile() {
stubUserLookup();
when(driverMapper.selectList(any())).thenReturn(
Collections.emptyList(),
List.of(driver(DRIVER_ID, null, PLATE), driver(9003L, null, "")));
DriverEnsureProfileVO result = service.ensureProfile(TENANT_ID, MP_USER_ID, MOBILE);
@@ -197,8 +198,8 @@ class DriverEnsureProfileTest {
@Test
@DisplayName("同手机号档案已属于其他账号:不覆盖,返回可读原因")
void rejectsMobileOwnedByAnotherAccount() {
stubUserLookup();
when(driverMapper.selectList(any())).thenReturn(
Collections.emptyList(),
List.of(driver(DRIVER_ID, OTHER_USER_ID, PLATE)));
DriverEnsureProfileVO result = service.ensureProfile(TENANT_ID, MP_USER_ID, MOBILE);
@@ -226,6 +227,19 @@ class DriverEnsureProfileTest {
// ------------------------------------------------------------ 夹具
/**
* 按 user_id 反查走 {@code getOne} → {@code baseMapper.selectOne};MyBatis-Plus 同时提供
* 单参与带 throwEx 两个重载,桩必须两个都打,否则 mock 返回默认值、反查永远落空。
*/
private void stubUserLookup() {
stubUserLookup((Driver) null);
}
private void stubUserLookup(Driver first, Driver... rest) {
when(driverMapper.selectOne(any())).thenReturn(first, rest);
when(driverMapper.selectOne(any(), anyBoolean())).thenReturn(first, rest);
}
private Driver driver(Long id, Long userId, String drivingVehicle) {
Driver driver = new Driver();
driver.setId(id);