DeviceTrustServiceTest.java 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. package com.ruoyi.app.user.service;
  2. import com.ruoyi.system.domain.InfoUserDevice;
  3. import com.ruoyi.system.mapper.InfoUserDeviceMapper;
  4. import org.junit.jupiter.api.Test;
  5. import static org.junit.jupiter.api.Assertions.assertEquals;
  6. import static org.junit.jupiter.api.Assertions.assertFalse;
  7. import static org.junit.jupiter.api.Assertions.assertNull;
  8. import static org.junit.jupiter.api.Assertions.assertSame;
  9. import static org.junit.jupiter.api.Assertions.assertTrue;
  10. import static org.mockito.ArgumentMatchers.any;
  11. import static org.mockito.ArgumentMatchers.anyString;
  12. import static org.mockito.Mockito.mock;
  13. import static org.mockito.Mockito.never;
  14. import static org.mockito.Mockito.verify;
  15. import static org.mockito.Mockito.verifyNoInteractions;
  16. import static org.mockito.Mockito.when;
  17. /**
  18. * DeviceTrustService 单元测试(029-device-trust-phone-bind,TDD 先行)。
  19. */
  20. class DeviceTrustServiceTest {
  21. private final InfoUserDeviceMapper mapper = mock(InfoUserDeviceMapper.class);
  22. private final DeviceTrustService service = new DeviceTrustService(mapper);
  23. // ---------- isValidDeviceId ----------
  24. @Test
  25. void nullOrEmptyOrOversizeDeviceIdIsInvalid() {
  26. assertFalse(DeviceTrustService.isValidDeviceId(null));
  27. assertFalse(DeviceTrustService.isValidDeviceId(""));
  28. assertFalse(DeviceTrustService.isValidDeviceId("x".repeat(65)));
  29. assertTrue(DeviceTrustService.isValidDeviceId("x".repeat(64)));
  30. assertTrue(DeviceTrustService.isValidDeviceId("dev-uuid-001"));
  31. }
  32. // ---------- recordLogin:首次 insert ----------
  33. @Test
  34. void firstVerifiedLoginInsertsNewTrustRowWithBothTimestamps() {
  35. when(mapper.selectById("dev-1")).thenReturn(null);
  36. service.recordLogin("dev-1", "0987654321", 100L);
  37. verify(mapper).insert(any(InfoUserDevice.class));
  38. verify(mapper, never()).updateById(any(InfoUserDevice.class));
  39. org.mockito.ArgumentCaptor<InfoUserDevice> captor =
  40. org.mockito.ArgumentCaptor.forClass(InfoUserDevice.class);
  41. verify(mapper).insert(captor.capture());
  42. InfoUserDevice saved = captor.getValue();
  43. assertEquals("dev-1", saved.getDeviceId());
  44. assertEquals("0987654321", saved.getPhone());
  45. assertEquals(100L, saved.getUserId());
  46. assertTrue(saved.getCreateTime() != null && saved.getUpdateTime() != null);
  47. }
  48. // ---------- recordLogin:同设备换号覆盖 ----------
  49. @Test
  50. void laterLoginWithDifferentPhoneOverwritesTrustRow() {
  51. InfoUserDevice exist = new InfoUserDevice();
  52. exist.setDeviceId("dev-1");
  53. exist.setPhone("0980000001");
  54. exist.setUserId(100L);
  55. when(mapper.selectById("dev-1")).thenReturn(exist);
  56. service.recordLogin("dev-1", "0987654321", 200L);
  57. verify(mapper).updateById(exist);
  58. verify(mapper, never()).insert(any(InfoUserDevice.class));
  59. assertEquals("0987654321", exist.getPhone());
  60. assertEquals(200L, exist.getUserId());
  61. assertTrue(exist.getUpdateTime() != null);
  62. }
  63. // ---------- recordLogin:非法入参静默跳过 ----------
  64. @Test
  65. void invalidDeviceIdOrMissingPhoneOrUserSkipsSilently() {
  66. service.recordLogin(null, "0987654321", 100L);
  67. service.recordLogin("", "0987654321", 100L);
  68. service.recordLogin("x".repeat(65), "0987654321", 100L);
  69. service.recordLogin("dev-1", null, 100L);
  70. service.recordLogin("dev-1", "0987654321", null);
  71. verifyNoInteractions(mapper);
  72. }
  73. // ---------- getTrust / getTrustedPhone ----------
  74. @Test
  75. void getTrustReturnsNullForInvalidDeviceIdWithoutQuery() {
  76. assertNull(service.getTrust(null));
  77. assertNull(service.getTrust(""));
  78. verifyNoInteractions(mapper);
  79. }
  80. @Test
  81. void getTrustedPhoneReturnsRowPhoneOrNull() {
  82. InfoUserDevice row = new InfoUserDevice();
  83. row.setDeviceId("dev-1");
  84. row.setPhone("0987654321");
  85. when(mapper.selectById("dev-1")).thenReturn(row);
  86. when(mapper.selectById("dev-2")).thenReturn(null);
  87. assertEquals("0987654321", service.getTrustedPhone("dev-1"));
  88. assertNull(service.getTrustedPhone("dev-2"));
  89. verify(mapper).selectById("dev-1");
  90. verify(mapper).selectById("dev-2");
  91. }
  92. // ---------- maskPhone(与现有日志脱敏规则一致:前3后4) ----------
  93. @Test
  94. void maskPhoneKeepsHead3Tail4AndMasksMiddle() {
  95. assertEquals("098****4321", DeviceTrustService.maskPhone("0987654321"));
  96. }
  97. @Test
  98. void maskPhoneReturnsShortValueAsIs() {
  99. assertNull(DeviceTrustService.maskPhone(null));
  100. assertEquals("1234567", DeviceTrustService.maskPhone("1234567"));
  101. }
  102. // ---------- 辅助:确认测试桩行为不受 anyString 干扰 ----------
  103. @Test
  104. void recordLoginSameDeviceTwiceOnlyQueriesByDeviceId() {
  105. when(mapper.selectById(anyString())).thenReturn(null);
  106. service.recordLogin("dev-1", "0987654321", 100L);
  107. service.recordLogin("dev-1", "0987654321", 100L);
  108. verify(mapper, org.mockito.Mockito.times(2)).selectById("dev-1");
  109. assertSame("0987654321", "0987654321");
  110. }
  111. }