puzhibing
7 小时以前 976ff3fe092ee2f9515013dbfab77d25b2944b75
ruoyi-service/ruoyi-order/src/test/java/com/ruoyi/order/service/impl/TChargingOrderServiceImplVinFallbackTest.java
@@ -18,6 +18,8 @@
import com.ruoyi.order.util.mongodb.service.UploadRealTimeMonitoringDataService;
import com.ruoyi.order.vo.EndOfChargePageInfo;
import com.baomidou.mybatisplus.core.MybatisConfiguration;
import com.baomidou.mybatisplus.core.conditions.AbstractWrapper;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
import com.ruoyi.system.api.model.LoginUserApplet;
import org.apache.ibatis.builder.MapperBuilderAssistant;
@@ -25,6 +27,7 @@
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;
@@ -32,13 +35,19 @@
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static org.junit.jupiter.api.Assertions.assertEquals;
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.verify;
import static org.mockito.Mockito.when;
/**
@@ -231,4 +240,98 @@
        assertNotNull(exception);
        assertEquals("充电订单不存在", exception.getMessage());
    }
    @Test
    void getChargingDetailsReturnsFinishedNormalOrderAndQueriesStatus5() {
        // 小程序主动结束充电后订单已结束(5),充电中页面仍需拿到该笔订单,
        // 用于关闭「请勿拔枪,正在结束充电」并展示「充电完成,可拔枪」
        LoginUserApplet loginUser = new LoginUserApplet();
        loginUser.setUserId(88L);
        when(tokenService.getLoginUserApplet()).thenReturn(loginUser);
        TChargingOrder order = new TChargingOrder();
        order.setId(3003L);
        order.setAppUserId(88L);
        order.setChargingGunId(5);
        order.setStatus(5);
        order.setCode("CH20261014001");
        order.setResidualAmount(new BigDecimal("20.00"));
        when(mapper.selectOne(any())).thenReturn(order);
        stubGunPileAndSite();
        when(uploadRealTimeMonitoringDataService.getLastDataById("CH20261014001")).thenReturn(null);
        ChargingDetails details = service.getChargingDetails(5);
        assertNotNull(details, "订单已结束时应返回完成态而非 null");
        assertEquals("3003", details.getId());
        assertEquals(Integer.valueOf(5), details.getStatus());
        assertEquals("CH20261014001", details.getCode());
        assertEquals(0, new BigDecimal("20.00").compareTo(details.getChargingCost()));
        @SuppressWarnings("unchecked")
        ArgumentCaptor<Wrapper<TChargingOrder>> captor = ArgumentCaptor.forClass(Wrapper.class);
        verify(mapper).selectOne(captor.capture());
        assertStatusFilterCoversFinished(captor.getValue());
    }
    @Test
    void getChargingDetailsReturnsFinishedVinOrderAndQueriesStatus5() {
        // VIN 码订单结束后同样需要返回完成态,兜底查询的状态过滤必须与主查询一致
        LoginUserApplet loginUser = new LoginUserApplet();
        loginUser.setUserId(88L);
        when(tokenService.getLoginUserApplet()).thenReturn(loginUser);
        when(mapper.selectOne(any())).thenReturn(null);
        TVinChargingOrder vinOrder = new TVinChargingOrder();
        vinOrder.setId(1001L);
        vinOrder.setAppUserId(88L);
        vinOrder.setChargingGunId(5);
        vinOrder.setStatus(5);
        vinOrder.setCode("VD20261014001");
        vinOrder.setResidualAmount(new BigDecimal("66.60"));
        when(vinChargingOrderMapper.selectOne(any())).thenReturn(vinOrder);
        stubGunPileAndSite();
        when(uploadRealTimeMonitoringDataService.getLastDataById("VD20261014001")).thenReturn(null);
        ChargingDetails details = service.getChargingDetails(5);
        assertNotNull(details, "VIN 订单已结束时应返回完成态而非 null");
        assertEquals(Integer.valueOf(5), details.getStatus());
        assertEquals("VD20261014001", details.getCode());
        @SuppressWarnings("unchecked")
        ArgumentCaptor<Wrapper<TVinChargingOrder>> captor = ArgumentCaptor.forClass(Wrapper.class);
        verify(vinChargingOrderMapper).selectOne(captor.capture());
        assertStatusFilterCoversFinished(captor.getValue());
    }
    /** getChargingDetails 组装链路依赖的充电枪/充电桩/站点远程调用 stub */
    private void stubGunPileAndSite() {
        TChargingGun gun = new TChargingGun();
        gun.setChargingPileId(7);
        when(chargingGunClient.getChargingGunById(5)).thenReturn(R.ok(gun));
        TChargingPile pile = new TChargingPile();
        pile.setName("1号桩");
        pile.setSiteId(9);
        when(chargingPileClient.getChargingPileById(7)).thenReturn(R.ok(pile));
        Site site = new Site();
        site.setName("城东站");
        when(siteClient.getSiteByIds(Arrays.asList(9))).thenReturn(R.ok(Collections.singletonList(site)));
    }
    /**
     * 断言订单查询条件中的 status 过滤覆盖 2、3、4、5。
     * 已结束(5) 必须在过滤范围内,否则小程序结束充电后拿不到订单,会一直停留在「正在结束充电」提示。
     */
    private void assertStatusFilterCoversFinished(Wrapper<?> wrapper) {
        AbstractWrapper<?, ?, ?> queryWrapper = (AbstractWrapper<?, ?, ?>) wrapper;
        Matcher inMatcher = Pattern.compile("status\\s+in\\s*\\(([^)]*)\\)", Pattern.CASE_INSENSITIVE)
                .matcher(queryWrapper.getSqlSegment());
        assertTrue(inMatcher.find(), "查询条件中应存在 status IN 过滤");
        List<Object> statusValues = new ArrayList<>();
        Matcher placeholderMatcher = Pattern.compile("MPGENVAL\\d+").matcher(inMatcher.group(1));
        while (placeholderMatcher.find()) {
            statusValues.add(queryWrapper.getParamNameValuePairs().get(placeholderMatcher.group()));
        }
        assertTrue(statusValues.containsAll(Arrays.asList(2, 3, 4, 5)),
                "status 过滤应包含 2,3,4,5,实际为:" + statusValues);
    }
}