package com.talentcard.server.business.auth; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.when; import java.util.Map; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.bean.override.mockito.MockitoBean; @SpringBootTest @ActiveProfiles("test") class TalentAuthServiceTests { @Autowired private JdbcTemplate jdbc; @Autowired private TalentAuthService talentAuthService; @MockitoBean private WeChatMiniProgramClient weChat; @BeforeEach void clearSessions() { jdbc.update("delete from talent_session"); } @Test void movesWechatBindingWhenSameWechatLogsInWithAnotherMobile() { String suffix = String.valueOf(System.nanoTime()); String openId = "openid-switch-" + suffix; String oldMobile = "136" + suffix.substring(suffix.length() - 8); String newMobile = "137" + suffix.substring(suffix.length() - 8); long oldTalentId = insertTalent("旧账号", oldMobile, openId, "OLD-" + suffix); long newTalentId = insertTalent("新账号", newMobile, null, "NEW-" + suffix); jdbc.update(""" insert into talent_session(talent_id, access_token_hash, refresh_token_hash, access_expires_at, refresh_expires_at, last_used_at) values (?, ?, ?, dateadd('HOUR', 1, current_timestamp), dateadd('DAY', 1, current_timestamp), current_timestamp) """, oldTalentId, "access-" + suffix, "refresh-" + suffix); when(weChat.exchangeOpenId("wechat-code")).thenReturn(openId); when(weChat.exchangePhoneNumber("phone-code")).thenReturn(newMobile); Map session = talentAuthService.login(new TalentLoginRequest("wechat-code", "phone-code", "v1", System.currentTimeMillis())); assertThat(((Number) session.get("talentId")).longValue()).isEqualTo(newTalentId); assertThat(jdbc.queryForObject("select openid from talent_user where id = ?", String.class, oldTalentId)).isNull(); assertThat(jdbc.queryForObject("select openid from talent_user where id = ?", String.class, newTalentId)).isEqualTo(openId); assertThat(jdbc.queryForObject("select count(*) from talent_session where talent_id = ? and revoked_at is null", Integer.class, oldTalentId)).isZero(); } private long insertTalent(String name, String mobile, String openId, String cardNo) { jdbc.update("insert into talent_user(openid, name, mobile, status, deleted) values (?, ?, ?, 1, 0)", openId, name, mobile); Long talentId = jdbc.queryForObject("select max(id) from talent_user", Long.class); assertThat(talentId).isNotNull(); jdbc.update("insert into talent_card(talent_id, card_no, card_type, card_level, status, deleted) values (?, ?, 'PERSONAL', '卓越人才卡', 1, 0)", talentId, cardNo); return talentId; } }