package com.ruoyi.order.service.impl; import com.ruoyi.chargingPile.api.feignClient.ChargingGunClient; import com.ruoyi.chargingPile.api.model.TChargingGun; import com.ruoyi.common.core.domain.R; import com.ruoyi.order.api.model.TCardChargingOrder; import com.ruoyi.order.mapper.TCardChargingOrderMapper; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.ArgumentCaptor; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.test.util.ReflectionTestUtils; import java.time.LocalDateTime; import java.util.Collections; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.lenient; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; /** * SD 握手处理单测:VIN 回写 + 仅状态=启动中(2)推进为充电中(3)。 */ @ExtendWith(MockitoExtension.class) class TCardChargingOrderHandshakeTest { private static final String VIN = "LFV3A23C8K3123456"; @InjectMocks private TCardChargingOrderServiceImpl service; @Mock private TCardChargingOrderMapper mapper; @Mock private ChargingGunClient chargingGunClient; @BeforeEach void setUp() { ReflectionTestUtils.setField(service, "baseMapper", mapper); // 启动中(2)→充电中(3)走条件更新 update(entity, wrapper),其余分支走 updateById lenient().when(mapper.update(any(TCardChargingOrder.class), any())).thenReturn(1); lenient().when(mapper.updateById(any(TCardChargingOrder.class))).thenReturn(1); } /** 握手推进时的枪状态查询与更新返回真实业务结果,避免静默跳过 */ private void mockGun(int gunId) { TChargingGun gun = new TChargingGun(); gun.setId(gunId); lenient().when(chargingGunClient.getChargingGunById(any())).thenReturn(R.ok(gun)); lenient().when(chargingGunClient.updateChargingGunById(any(TChargingGun.class))).thenReturn(R.ok()); } private void mockOrder(TCardChargingOrder order) { lenient().when(mapper.selectOne(any())).thenReturn(order); lenient().when(mapper.selectList(any())) .thenReturn(order == null ? Collections.emptyList() : Collections.singletonList(order)); } private TCardChargingOrder order(Integer status) { TCardChargingOrder order = new TCardChargingOrder(); order.setId(1001L); order.setCode("SD20260909001"); order.setStatus(status); order.setChargingGunId(5); return order; } @Test void advancesStartingOrderToChargingAndWritesVin() { TCardChargingOrder order = order(2); mockOrder(order); mockGun(5); assertTrue(service.handleHandshakeVin("SD20260909001", VIN)); ArgumentCaptor orderCaptor = ArgumentCaptor.forClass(TCardChargingOrder.class); verify(mapper).update(orderCaptor.capture(), any()); TCardChargingOrder update = orderCaptor.getValue(); assertEquals(3, update.getStatus()); assertEquals(VIN, update.getActualVin()); assertNotNull(update.getStartTime()); ArgumentCaptor gunCaptor = ArgumentCaptor.forClass(TChargingGun.class); verify(chargingGunClient).updateChargingGunById(gunCaptor.capture()); TChargingGun gun = gunCaptor.getValue(); assertEquals(Integer.valueOf(5), gun.getId()); assertEquals(Integer.valueOf(4), gun.getStatus()); } @Test void keepsExistingStartTimeWhenAdvancing() { TCardChargingOrder order = order(2); LocalDateTime existed = LocalDateTime.now().minusMinutes(10); order.setStartTime(existed); mockOrder(order); mockGun(5); assertTrue(service.handleHandshakeVin("SD20260909001", VIN)); ArgumentCaptor captor = ArgumentCaptor.forClass(TCardChargingOrder.class); verify(mapper).update(captor.capture(), any()); assertNull(captor.getValue().getStartTime()); } @Test void advancesStartingOrderEvenWhenVinBlank() { TCardChargingOrder order = order(2); mockOrder(order); mockGun(5); assertTrue(service.handleHandshakeVin("SD20260909001", "")); ArgumentCaptor captor = ArgumentCaptor.forClass(TCardChargingOrder.class); verify(mapper).update(captor.capture(), any()); assertEquals(3, captor.getValue().getStatus()); assertNull(captor.getValue().getActualVin()); verify(chargingGunClient).updateChargingGunById(any(TChargingGun.class)); } @Test void doesNotReviveStartFailedOrder() { TCardChargingOrder order = order(-1); mockOrder(order); assertTrue(service.handleHandshakeVin("SD20260909001", VIN)); ArgumentCaptor captor = ArgumentCaptor.forClass(TCardChargingOrder.class); verify(mapper).updateById(captor.capture()); assertNull(captor.getValue().getStatus()); assertEquals(VIN, captor.getValue().getActualVin()); verify(chargingGunClient, never()).updateChargingGunById(any(TChargingGun.class)); } @Test void skipsAdvancementForChargingOrder() { TCardChargingOrder order = order(3); mockOrder(order); assertTrue(service.handleHandshakeVin("SD20260909001", VIN)); ArgumentCaptor captor = ArgumentCaptor.forClass(TCardChargingOrder.class); verify(mapper).updateById(captor.capture()); assertNull(captor.getValue().getStatus()); assertEquals(VIN, captor.getValue().getActualVin()); verify(chargingGunClient, never()).updateChargingGunById(any(TChargingGun.class)); } @Test void skipsUpdateEntirelyForFinishedOrderWithoutVin() { TCardChargingOrder order = order(5); mockOrder(order); assertTrue(service.handleHandshakeVin("SD20260909001", "")); verify(mapper, never()).updateById(any(TCardChargingOrder.class)); verify(chargingGunClient, never()).updateChargingGunById(any(TChargingGun.class)); } @Test void returnsFalseWhenOrderMissing() { mockOrder(null); assertFalse(service.handleHandshakeVin("SD20260909001", VIN)); verify(mapper, never()).updateById(any(TCardChargingOrder.class)); verify(chargingGunClient, never()).updateChargingGunById(any(TChargingGun.class)); } }