package com.battery.business.service.impl; import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*; import static org.junit.jupiter.api.Assertions.assertEquals; import java.math.BigDecimal; import java.util.Date; import java.util.List; import org.junit.jupiter.api.Test; import com.battery.business.domain.TTest; import com.battery.business.domain.TTestWarningException; import com.battery.business.domain.TTestWarningThreshold; import com.battery.business.mapper.TTestMapper; /** 阈值异常与接收中的离线异常分别判定,并通过持久层原子聚合。 */ class TestWarningExceptionServiceTest { @Test void recordsOfflineSourcesOnlyWhileReceivingWithoutInventingMeasurements() { TTestMapper mapper = mock(TTestMapper.class); var service = new TestWarningExceptionService(mapper); TTest test = new TTest(); test.setTestId(1L); test.setTestStatus("RUNNING"); test.setReceptionStatus("RECEIVING"); Date now = new Date(); when(mapper.selectOfflineTestSources(1L)).thenReturn(List.of( new com.battery.business.domain.vo.OfflineTestSource("CABINET_CHANNEL", "sim:22:1:1:1"), new com.battery.business.domain.vo.OfflineTestSource("COLLECTOR", "9"))); service.recordOfflineSources(test, now); verify(mapper).upsertOfflineException(1L, "CABINET_CHANNEL", "sim:22:1:1:1", now); verify(mapper).upsertOfflineException(1L, "COLLECTOR", "9", now); clearInvocations(mapper); for (String state : List.of("PAUSED", "ENDED", "NOT_STARTED")) { test.setReceptionStatus(state); service.recordOfflineSources(test, now); } verifyNoInteractions(mapper); } @Test void evaluatesOnlyOutOfRangeValues() { TTestMapper mapper = mock(TTestMapper.class); TestWarningExceptionService service = new TestWarningExceptionService(mapper); TTest test = testWithThreshold("TEMPERATURE", new BigDecimal("0"), new BigDecimal("30")); service.evaluate(test, "COLLECTOR", "adapter:9:S-01", "temperature", new BigDecimal("31"), "℃", new Date()); service.evaluate(test, "COLLECTOR", "adapter:9:S-01", "temperature", new BigDecimal("20"), "℃", new Date()); service.evaluate(test, "COLLECTOR", "adapter:9:S-01", "temperature", new BigDecimal("0"), "℃", new Date()); service.evaluate(test, "COLLECTOR", "adapter:9:S-01", "temperature", new BigDecimal("30"), "℃", new Date()); service.evaluate(test, "COLLECTOR", "adapter:9:S-01", "temperature", null, "℃", new Date()); verify(mapper, times(1)).upsertWarningException(eq(1L), eq(11L), eq("COLLECTOR"), eq("adapter:9:S-01"), eq("temperature"), eq(new BigDecimal("31")), eq("℃"), anyString(), eq("WARNING"), any(Date.class)); } @Test void nonReceivingTestsDoNotCreateThresholdTodos() { var mapper = mock(TTestMapper.class); var service = new TestWarningExceptionService(mapper); var test = testWithThreshold("TEMPERATURE", new BigDecimal("8"), new BigDecimal("33")); for (String reception : List.of("PAUSED", "ENDED", "NOT_STARTED")) { test.setReceptionStatus(reception); service.evaluate(test, "COLLECTOR", "9:S-01", "temperature", new BigDecimal("38"), "℃", new Date()); } verifyNoInteractions(mapper); } @Test void closesOpenExceptionAndAppendsAuditInServiceOperation() { TTestMapper mapper = mock(TTestMapper.class); TestWarningExceptionService service = new TestWarningExceptionService(mapper); TTestWarningException exception = new TTestWarningException(); exception.setExceptionId(7L); exception.setTestId(1L); when(mapper.selectWarningExceptionById(7L)).thenReturn(exception); when(mapper.closeWarningException(eq(7L), eq(22L), eq("负责人"), any(Date.class), eq("已核实"))).thenReturn(1); int rows = service.close(7L, 22L, "负责人", "已核实"); assertEquals(1, rows); } private static TTest testWithThreshold(String metric, BigDecimal min, BigDecimal max) { TTestWarningThreshold threshold = new TTestWarningThreshold(); threshold.setThresholdId(11L); threshold.setMetricCode(metric); threshold.setMinValue(min); threshold.setMaxValue(max); threshold.setUnit("℃"); threshold.setSeverity("WARNING"); TTest test = new TTest(); test.setTestId(1L); test.setThresholds(List.of(threshold)); test.setTestStatus("RUNNING"); test.setReceptionStatus("RECEIVING"); return test; } }