package com.ruoyi.order.service.impl;
|
|
import com.baomidou.mybatisplus.core.MybatisConfiguration;
|
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
|
import com.ruoyi.chargingPile.api.dto.GetSiteListDTO;
|
import com.ruoyi.chargingPile.api.feignClient.ChargingGunClient;
|
import com.ruoyi.chargingPile.api.feignClient.ChargingPileClient;
|
import com.ruoyi.chargingPile.api.feignClient.SiteClient;
|
import com.ruoyi.chargingPile.api.model.TChargingGun;
|
import com.ruoyi.chargingPile.api.model.TChargingPile;
|
import com.ruoyi.common.core.domain.R;
|
import com.ruoyi.common.core.web.domain.AjaxResult;
|
import com.ruoyi.common.security.service.TokenService;
|
import com.ruoyi.integration.api.feignClient.SendMessageClient;
|
import com.ruoyi.integration.api.model.PlatformStopCharging;
|
import com.ruoyi.order.api.model.TCardChargingOrder;
|
import com.ruoyi.order.mapper.TCardChargingOrderMapper;
|
import com.ruoyi.system.api.model.LoginUser;
|
import org.apache.ibatis.builder.MapperBuilderAssistant;
|
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.util.Collections;
|
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
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;
|
|
/**
|
* 管理后台刷卡充电订单「停止充电」单测。
|
* 覆盖:数据范围校验、充电枪匹配、状态拦截、条件更新并发保护、停机指令下发。
|
*/
|
@ExtendWith(MockitoExtension.class)
|
class TCardChargingOrderStopChargingTest {
|
|
private static final Long LOGIN_USER_ID = 9L;
|
private static final Integer AUTHORIZED_SITE_ID = 7;
|
private static final Long ORDER_ID = 11L;
|
private static final Integer GUN_ID = 22;
|
private static final Integer PILE_ID = 33;
|
|
@InjectMocks
|
private TCardChargingOrderServiceImpl service;
|
@Mock
|
private TCardChargingOrderMapper mapper;
|
@Mock
|
private TokenService tokenService;
|
@Mock
|
private SiteClient siteClient;
|
@Mock
|
private ChargingGunClient chargingGunClient;
|
@Mock
|
private ChargingPileClient chargingPileClient;
|
@Mock
|
private SendMessageClient sendMessageClient;
|
|
@BeforeEach
|
void setUp() {
|
ReflectionTestUtils.setField(service, "baseMapper", mapper);
|
// lambdaUpdate 解析 getter 引用依赖 MyBatis-Plus 实体元信息缓存,单测环境需显式初始化
|
TableInfoHelper.initTableInfo(new MapperBuilderAssistant(new MybatisConfiguration(), ""),
|
TCardChargingOrder.class);
|
// 默认:条件更新成功
|
lenient().when(mapper.update(any(), any())).thenReturn(1);
|
}
|
|
// ===== 一、正常停充 =====
|
|
@Test
|
void stopChargingAdvancesStatusAndSendsCommand() {
|
TCardChargingOrder order = order(3);
|
when(mapper.selectById(ORDER_ID)).thenReturn(order);
|
mockAuthorizedLogin();
|
mockDevice(order);
|
|
AjaxResult result = service.stopCharging(String.valueOf(ORDER_ID), GUN_ID);
|
|
assertEquals(Integer.valueOf(200), result.get("code"));
|
ArgumentCaptor<PlatformStopCharging> captor = ArgumentCaptor.forClass(PlatformStopCharging.class);
|
verify(sendMessageClient).platformStopCharging(captor.capture());
|
assertEquals("PILE-33", captor.getValue().getCharging_pile_code());
|
assertEquals("GUN-22", captor.getValue().getCharging_gun_code());
|
assertEquals(Integer.valueOf(4), order.getStatus());
|
assertEquals(Integer.valueOf(1), order.getEndMode());
|
verify(mapper).update(any(), any());
|
}
|
|
// ===== 二、入参与订单校验 =====
|
|
@Test
|
void rejectsInvalidOrderId() {
|
AjaxResult result = service.stopCharging("abc", GUN_ID);
|
|
assertEquals(Integer.valueOf(500), result.get("code"));
|
assertEquals("刷卡充电订单ID无效", result.get("msg"));
|
verify(sendMessageClient, never()).platformStopCharging(any(PlatformStopCharging.class));
|
}
|
|
@Test
|
void rejectsOrderNotFound() {
|
when(mapper.selectById(ORDER_ID)).thenReturn(null);
|
|
AjaxResult result = service.stopCharging(String.valueOf(ORDER_ID), GUN_ID);
|
|
assertEquals(Integer.valueOf(500), result.get("code"));
|
assertEquals("刷卡充电订单不存在或无权操作", result.get("msg"));
|
verify(sendMessageClient, never()).platformStopCharging(any(PlatformStopCharging.class));
|
}
|
|
@Test
|
void rejectsOrderOutsideAuthorizationScope() {
|
TCardChargingOrder order = order(3);
|
order.setSiteId(AUTHORIZED_SITE_ID + 1);
|
when(mapper.selectById(ORDER_ID)).thenReturn(order);
|
mockAuthorizedLogin();
|
|
AjaxResult result = service.stopCharging(String.valueOf(ORDER_ID), GUN_ID);
|
|
assertEquals(Integer.valueOf(500), result.get("code"));
|
assertEquals("刷卡充电订单不存在或无权操作", result.get("msg"));
|
verify(sendMessageClient, never()).platformStopCharging(any(PlatformStopCharging.class));
|
}
|
|
@Test
|
void rejectsMismatchedGun() {
|
TCardChargingOrder order = order(3);
|
when(mapper.selectById(ORDER_ID)).thenReturn(order);
|
mockAuthorizedLogin();
|
|
AjaxResult result = service.stopCharging(String.valueOf(ORDER_ID), GUN_ID + 1);
|
|
assertEquals(Integer.valueOf(500), result.get("code"));
|
assertEquals("充电枪与订单不匹配", result.get("msg"));
|
verify(sendMessageClient, never()).platformStopCharging(any(PlatformStopCharging.class));
|
}
|
|
// ===== 三、状态拦截 =====
|
|
@Test
|
void rejectsOrderNotStartedCharge() {
|
TCardChargingOrder order = order(2);
|
when(mapper.selectById(ORDER_ID)).thenReturn(order);
|
mockAuthorizedLogin();
|
|
AjaxResult result = service.stopCharging(String.valueOf(ORDER_ID), GUN_ID);
|
|
assertEquals(Integer.valueOf(500), result.get("code"));
|
assertEquals("还未开始充电", result.get("msg"));
|
verify(sendMessageClient, never()).platformStopCharging(any(PlatformStopCharging.class));
|
}
|
|
@Test
|
void rejectsRepeatedStopOperation() {
|
TCardChargingOrder order = order(4);
|
when(mapper.selectById(ORDER_ID)).thenReturn(order);
|
mockAuthorizedLogin();
|
|
AjaxResult result = service.stopCharging(String.valueOf(ORDER_ID), GUN_ID);
|
|
assertEquals(Integer.valueOf(500), result.get("code"));
|
assertEquals("不能重复操作", result.get("msg"));
|
verify(sendMessageClient, never()).platformStopCharging(any(PlatformStopCharging.class));
|
}
|
|
// ===== 四、设备与并发 =====
|
|
@Test
|
void rejectsWhenDeviceMissing() {
|
TCardChargingOrder order = order(3);
|
when(mapper.selectById(ORDER_ID)).thenReturn(order);
|
mockAuthorizedLogin();
|
|
AjaxResult result = service.stopCharging(String.valueOf(ORDER_ID), GUN_ID);
|
|
assertEquals(Integer.valueOf(500), result.get("code"));
|
assertEquals("未找到订单对应的充电设备", result.get("msg"));
|
verify(sendMessageClient, never()).platformStopCharging(any(PlatformStopCharging.class));
|
}
|
|
@Test
|
void rejectsWhenStatusChangedConcurrently() {
|
lenient().when(mapper.update(any(), any())).thenReturn(0);
|
TCardChargingOrder order = order(3);
|
when(mapper.selectById(ORDER_ID)).thenReturn(order);
|
mockAuthorizedLogin();
|
mockDevice(order);
|
|
AjaxResult result = service.stopCharging(String.valueOf(ORDER_ID), GUN_ID);
|
|
assertEquals(Integer.valueOf(500), result.get("code"));
|
assertEquals("订单状态已变化,请刷新后重试", result.get("msg"));
|
verify(sendMessageClient, never()).platformStopCharging(any(PlatformStopCharging.class));
|
}
|
|
// ===== 辅助方法 =====
|
|
private TCardChargingOrder order(Integer status) {
|
TCardChargingOrder order = new TCardChargingOrder();
|
order.setId(ORDER_ID);
|
order.setCode("SD202610140001");
|
order.setSiteId(AUTHORIZED_SITE_ID);
|
order.setChargingGunId(GUN_ID);
|
order.setChargingPileId(PILE_ID);
|
order.setStatus(status);
|
return order;
|
}
|
|
private void mockAuthorizedLogin() {
|
LoginUser loginUser = new LoginUser();
|
loginUser.setUserid(LOGIN_USER_ID);
|
lenient().when(tokenService.getLoginUser()).thenReturn(loginUser);
|
GetSiteListDTO site = new GetSiteListDTO();
|
site.setId(AUTHORIZED_SITE_ID);
|
lenient().when(siteClient.getSiteListByUserId(LOGIN_USER_ID))
|
.thenReturn(R.ok(Collections.singletonList(site)));
|
}
|
|
private void mockDevice(TCardChargingOrder order) {
|
TChargingGun gun = new TChargingGun();
|
gun.setId(order.getChargingGunId());
|
gun.setCode("GUN-" + order.getChargingGunId());
|
lenient().when(chargingGunClient.getChargingGunById(order.getChargingGunId())).thenReturn(R.ok(gun));
|
TChargingPile pile = new TChargingPile();
|
pile.setId(order.getChargingPileId());
|
pile.setCode("PILE-" + order.getChargingPileId());
|
lenient().when(chargingPileClient.getChargingPileById(order.getChargingPileId())).thenReturn(R.ok(pile));
|
}
|
}
|