package com.battery.business.service.impl;
|
|
import static org.junit.jupiter.api.Assertions.*;
|
import static org.mockito.Mockito.*;
|
import static org.mockito.ArgumentMatchers.*;
|
import java.math.BigDecimal;
|
import java.util.List;
|
import java.util.Map;
|
import org.junit.jupiter.api.Test;
|
import com.alibaba.fastjson2.JSON;
|
import com.battery.business.domain.*;
|
import com.battery.business.mapper.TTestMapper;
|
import com.ruoyi.common.exception.ServiceException;
|
|
/** 修订入口必须保留数据库中的修改前事实,并拒绝越界身份和字段。 */
|
class TestConsoleDataRevisionQueryServiceTest
|
{
|
private final TTestMapper mapper = mock(TTestMapper.class);
|
private final TestConsoleDataServiceImpl service = new TestConsoleDataServiceImpl(mapper);
|
|
@Test void savesDatabaseBeforeContentInsteadOfClientClaims()
|
{
|
var action = action("EDIT", "realtime:7");
|
when(mapper.selectDataRecord(1L, "REALTIME", 7L)).thenReturn(Map.of("voltage_v", new BigDecimal("3.7"), "source_identity", "cabinet-a"));
|
var item = new DataRevisionItem(); item.setStableIdentity("realtime:7"); item.setFieldValues("{\"voltage\":4.125}");
|
service.submitAction(action, List.of(item));
|
var before = JSON.parseArray(action.getBeforeContentJson()).getJSONObject(0);
|
assertEquals("cabinet-a", before.getString("source_identity"));
|
assertEquals(new BigDecimal("3.7"), before.getBigDecimal("voltage_v"));
|
var order = inOrder(mapper);
|
order.verify(mapper).insertDataRevisionAction(action);
|
order.verify(mapper).updateDataRecord(1L, "REALTIME", 7L, Map.of("voltage_v", new BigDecimal("4.125")));
|
}
|
|
@Test void deletionPersistsCompleteContentBeforeRemovingRecord()
|
{
|
var action = action("DELETE", "realtime:7");
|
when(mapper.selectDataRecord(1L, "REALTIME", 7L)).thenReturn(Map.of("cabinet_device_time_raw", "2026-09-05 12:00:00", "voltage_v", 3.7));
|
service.submitAction(action, List.of());
|
assertTrue(action.getBeforeContentJson().contains("cabinet_device_time_raw"));
|
var order = inOrder(mapper);
|
order.verify(mapper).insertDataRevisionAction(action);
|
order.verify(mapper).deleteDataRecord(1L, "REALTIME", 7L);
|
}
|
|
@Test void stepExtensionEditPreservesOtherMetricsAndDisplaysPreviousValue()
|
{
|
var action = action("EDIT", "step:7"); action.setDataType("STEP");
|
when(mapper.selectDataRecord(1L, "STEP", 7L)).thenReturn(Map.of("extension_measurements_json", "{\"startVoltage\":3.2,\"stepDuration\":60}"));
|
var item = new DataRevisionItem(); item.setStableIdentity("step:7"); item.setFieldValues("{\"startVoltage\":3.4}");
|
service.submitAction(action, List.of(item));
|
var change = JSON.parseArray(action.getChangesSummary()).getJSONObject(0);
|
assertEquals(new BigDecimal("3.2"), change.getJSONObject("before").getBigDecimal("startVoltage"));
|
var values = org.mockito.ArgumentCaptor.forClass(Map.class);
|
verify(mapper).updateDataRecord(eq(1L), eq("STEP"), eq(7L), values.capture());
|
var extension = JSON.parseObject(values.getValue().get("extension_measurements_json").toString());
|
assertEquals(60, extension.getIntValue("stepDuration"));
|
assertEquals(new BigDecimal("3.4"), extension.getBigDecimal("startVoltage"));
|
}
|
|
@Test void rejectsWrongDataTypeIdentityAndOtherTestsRecords()
|
{
|
assertThrows(ServiceException.class, () -> service.submitAction(action("DELETE", "step:7"), List.of()));
|
assertThrows(ServiceException.class, () -> service.submitAction(action("DELETE", "realtime:8"), List.of()));
|
verify(mapper, never()).insertDataRevisionAction(any());
|
}
|
|
@Test void rejectsIdentityEditsAndNonNumericMeasurements()
|
{
|
when(mapper.selectDataRecord(1L, "REALTIME", 7L)).thenReturn(Map.of("voltage_v", 3.7));
|
for (String fields : List.of("{\"test_id\":2}", "{\"voltage\":\"invalid\"}")) {
|
var item = new DataRevisionItem(); item.setStableIdentity("realtime:7"); item.setFieldValues(fields);
|
assertThrows(ServiceException.class, () -> service.submitAction(action("EDIT", "realtime:7"), List.of(item)));
|
}
|
verify(mapper, never()).insertDataRevisionAction(any());
|
}
|
|
@Test void importRequiresCompletedTest()
|
{
|
assertThrows(ServiceException.class, () -> service.submitAction(action("IMPORT", "manual-1"), List.of()));
|
verify(mapper, never()).insertImportedDataRecord(anyString(), any());
|
}
|
|
@Test void completedRealtimeImportKeepsSourceRecordAndSequence()
|
{
|
var action = action("IMPORT", "manual-1");
|
mapper.selectTestByIdForUpdate(1L).setTestStatus("COMPLETED");
|
when(mapper.selectImportBinding(1L, "BAT-1")).thenReturn(Map.of("test_battery_id", 4L, "binding_id", 5L, "adapter_code", "adapter-a", "devtype", 27, "devid", 1, "subdevid", 1, "chlid", 1));
|
action.setChangesSummary("[{\"recordNo\":\"manual-1\",\"batteryNo\":\"BAT-1\",\"recordedAt\":1770000000123,\"cycleNo\":1,\"stepNo\":1,\"stepName\":\"恒流充电\",\"sequenceId\":17,\"voltage\":3.6}]");
|
service.submitAction(action, List.of());
|
var values = org.mockito.ArgumentCaptor.forClass(Map.class);
|
verify(mapper).insertImportedDataRecord(eq("REALTIME"), values.capture());
|
assertEquals("manual-1", values.getValue().get("source_record_id"));
|
assertEquals(17L, values.getValue().get("cabinet_sequence_id"));
|
assertEquals("adapter-a:27:1:1:1", values.getValue().get("source_identity"));
|
}
|
|
private TTestDataRevisionAction action(String operation, String identity)
|
{
|
TTest test = new TTest(); test.setTestId(1L); test.setTestStatus("RUNNING");
|
when(mapper.selectTestByIdForUpdate(1L)).thenReturn(test);
|
var action = new TTestDataRevisionAction(); action.setTestId(1L); action.setDataType("REALTIME");
|
action.setOperationType(operation); action.setIdentitySummary(JSON.toJSONString(List.of(identity)));
|
action.setScopeSummary("核对一条数据"); action.setReason("现场核对"); action.setOperatorName("operator");
|
action.setChangesSummary("[]"); return action;
|
}
|
}
|