TbGpsGeofencingActionNodeTest:

added extends AbstractRuleNodeUpgradeTest
added @ExtendWith(MockitoExtension.class) and refactored
This commit is contained in:
artem 2024-02-03 21:59:33 +02:00
parent 016d8734aa
commit 8cdde9e67c

View File

@ -15,40 +15,37 @@
*/ */
package org.thingsboard.rule.engine.geo; package org.thingsboard.rule.engine.geo;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.util.concurrent.Futures;
import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource; import org.junit.jupiter.params.provider.MethodSource;
import org.mockito.ArgumentCaptor; import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.test.util.ReflectionTestUtils; import org.springframework.test.util.ReflectionTestUtils;
import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.common.util.JacksonUtil;
import org.thingsboard.rule.engine.AbstractRuleNodeUpgradeTest;
import org.thingsboard.rule.engine.api.TbContext; import org.thingsboard.rule.engine.api.TbContext;
import org.thingsboard.rule.engine.api.TbNode;
import org.thingsboard.rule.engine.api.TbNodeConfiguration; import org.thingsboard.rule.engine.api.TbNodeConfiguration;
import org.thingsboard.rule.engine.api.TbNodeException; import org.thingsboard.rule.engine.api.TbNodeException;
import org.thingsboard.server.common.data.DataConstants;
import org.thingsboard.server.common.data.id.DeviceId; import org.thingsboard.server.common.data.id.DeviceId;
import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.msg.TbMsgType; import org.thingsboard.server.common.data.msg.TbMsgType;
import org.thingsboard.server.common.data.util.TbPair;
import org.thingsboard.server.common.msg.TbMsg; import org.thingsboard.server.common.msg.TbMsg;
import org.thingsboard.server.common.msg.TbMsgMetaData; import org.thingsboard.server.common.msg.TbMsgMetaData;
import org.thingsboard.server.dao.attributes.AttributesService; import org.thingsboard.server.dao.attributes.AttributesService;
import java.time.Duration; import java.time.Duration;
import java.util.Optional;
import java.util.UUID; import java.util.UUID;
import java.util.stream.Stream; import java.util.stream.Stream;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never; import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times; import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import static org.thingsboard.rule.engine.util.GpsGeofencingEvents.ENTERED; import static org.thingsboard.rule.engine.util.GpsGeofencingEvents.ENTERED;
@ -57,16 +54,17 @@ import static org.thingsboard.rule.engine.util.GpsGeofencingEvents.LEFT;
import static org.thingsboard.rule.engine.util.GpsGeofencingEvents.OUTSIDE; import static org.thingsboard.rule.engine.util.GpsGeofencingEvents.OUTSIDE;
import static org.thingsboard.server.common.data.msg.TbNodeConnectionType.SUCCESS; import static org.thingsboard.server.common.data.msg.TbNodeConnectionType.SUCCESS;
class TbGpsGeofencingActionNodeTest { @ExtendWith(MockitoExtension.class)
class TbGpsGeofencingActionNodeTest extends AbstractRuleNodeUpgradeTest {
@Mock
private TbContext ctx; private TbContext ctx;
private TbGpsGeofencingActionNode node; @Mock
private AttributesService attributesService; private AttributesService attributesService;
private TbGpsGeofencingActionNode node;
@BeforeEach @BeforeEach
void setUp() { void setUp() {
ctx = mock(TbContext.class); node = spy(new TbGpsGeofencingActionNode());
attributesService = mock(AttributesService.class);
node = new TbGpsGeofencingActionNode();
} }
@AfterEach @AfterEach
@ -80,23 +78,37 @@ class TbGpsGeofencingActionNodeTest {
long tsNowMinusMinuteAndMillis = tsNow - Duration.ofMinutes(1).plusMillis(1).toMillis(); long tsNowMinusMinuteAndMillis = tsNow - Duration.ofMinutes(1).plusMillis(1).toMillis();
return Stream.of( return Stream.of(
// default config with presenceMonitoringStrategyOnEachMessage false and msgInside true // default config with presenceMonitoringStrategyOnEachMessage false and msgInside true
Arguments.of(new GpsGeofencingActionTestCase(deviceId, true, false, new EntityGeofencingState(false, 0, false)), ENTERED), Arguments.of(new GpsGeofencingActionTestCase(deviceId, true, false,
Arguments.of(new GpsGeofencingActionTestCase(deviceId, true, false, new EntityGeofencingState(true, tsNow, false)), SUCCESS), new EntityGeofencingState(false, 0, false)), ENTERED),
Arguments.of(new GpsGeofencingActionTestCase(deviceId, true, false, new EntityGeofencingState(true, tsNowMinusMinuteAndMillis, false)), INSIDE), Arguments.of(new GpsGeofencingActionTestCase(deviceId, true, false,
Arguments.of(new GpsGeofencingActionTestCase(deviceId, true, false, new EntityGeofencingState(true, tsNow, true)), SUCCESS), new EntityGeofencingState(true, tsNow, false)), SUCCESS),
Arguments.of(new GpsGeofencingActionTestCase(deviceId, true, false,
new EntityGeofencingState(true, tsNowMinusMinuteAndMillis, false)), INSIDE),
Arguments.of(new GpsGeofencingActionTestCase(deviceId, true, false,
new EntityGeofencingState(true, tsNow, true)), SUCCESS),
// default config with presenceMonitoringStrategyOnEachMessage false and msgInside false // default config with presenceMonitoringStrategyOnEachMessage false and msgInside false
Arguments.of(new GpsGeofencingActionTestCase(deviceId, false, false, new EntityGeofencingState(false, 0, false)), LEFT), Arguments.of(new GpsGeofencingActionTestCase(deviceId, false, false,
Arguments.of(new GpsGeofencingActionTestCase(deviceId, false, false, new EntityGeofencingState(false, tsNow, false)), SUCCESS), new EntityGeofencingState(false, 0, false)), LEFT),
Arguments.of(new GpsGeofencingActionTestCase(deviceId, false, false, new EntityGeofencingState(false, tsNowMinusMinuteAndMillis, false)), OUTSIDE), Arguments.of(new GpsGeofencingActionTestCase(deviceId, false, false,
Arguments.of(new GpsGeofencingActionTestCase(deviceId, false, false, new EntityGeofencingState(false, tsNow, true)), SUCCESS), new EntityGeofencingState(false, tsNow, false)), SUCCESS),
Arguments.of(new GpsGeofencingActionTestCase(deviceId, false, false,
new EntityGeofencingState(false, tsNowMinusMinuteAndMillis, false)), OUTSIDE),
Arguments.of(new GpsGeofencingActionTestCase(deviceId, false, false,
new EntityGeofencingState(false, tsNow, true)), SUCCESS),
// default config with presenceMonitoringStrategyOnEachMessage true and msgInside true // default config with presenceMonitoringStrategyOnEachMessage true and msgInside true
Arguments.of(new GpsGeofencingActionTestCase(deviceId, true, true, new EntityGeofencingState(false, 0, false)), ENTERED), Arguments.of(new GpsGeofencingActionTestCase(deviceId, true, true,
Arguments.of(new GpsGeofencingActionTestCase(deviceId, true, true, new EntityGeofencingState(true, tsNow, false)), INSIDE), new EntityGeofencingState(false, 0, false)), ENTERED),
Arguments.of(new GpsGeofencingActionTestCase(deviceId, true, true, new EntityGeofencingState(true, tsNowMinusMinuteAndMillis, false)), INSIDE), Arguments.of(new GpsGeofencingActionTestCase(deviceId, true, true,
new EntityGeofencingState(true, tsNow, false)), INSIDE),
Arguments.of(new GpsGeofencingActionTestCase(deviceId, true, true,
new EntityGeofencingState(true, tsNowMinusMinuteAndMillis, false)), INSIDE),
// default config with presenceMonitoringStrategyOnEachMessage true and msgInside false // default config with presenceMonitoringStrategyOnEachMessage true and msgInside false
Arguments.of(new GpsGeofencingActionTestCase(deviceId, false, true, new EntityGeofencingState(false, 0, false)), LEFT), Arguments.of(new GpsGeofencingActionTestCase(deviceId, false, true,
Arguments.of(new GpsGeofencingActionTestCase(deviceId, false, true, new EntityGeofencingState(false, tsNow, false)), OUTSIDE), new EntityGeofencingState(false, 0, false)), LEFT),
Arguments.of(new GpsGeofencingActionTestCase(deviceId, false, true, new EntityGeofencingState(false, tsNowMinusMinuteAndMillis, false)), OUTSIDE) Arguments.of(new GpsGeofencingActionTestCase(deviceId, false, true,
new EntityGeofencingState(false, tsNow, false)), OUTSIDE),
Arguments.of(new GpsGeofencingActionTestCase(deviceId, false, true,
new EntityGeofencingState(false, tsNowMinusMinuteAndMillis, false)), OUTSIDE)
); );
} }
@ -117,10 +129,6 @@ class TbGpsGeofencingActionNodeTest {
getOutsideRectangleTbMsg(gpsGeofencingActionTestCase.getEntityId()); getOutsideRectangleTbMsg(gpsGeofencingActionTestCase.getEntityId());
when(ctx.getAttributesService()).thenReturn(attributesService); when(ctx.getAttributesService()).thenReturn(attributesService);
when(ctx
.getAttributesService()
.find(ctx.getTenantId(), msg.getOriginator(), DataConstants.SERVER_SCOPE, ctx.getServiceId()))
.thenReturn(Futures.immediateFuture(Optional.empty()));
ReflectionTestUtils.setField(node, "entityStates", gpsGeofencingActionTestCase.getEntityStates()); ReflectionTestUtils.setField(node, "entityStates", gpsGeofencingActionTestCase.getEntityStates());
@ -128,24 +136,16 @@ class TbGpsGeofencingActionNodeTest {
node.onMsg(ctx, msg); node.onMsg(ctx, msg);
// THEN // THEN
verify(ctx.getAttributesService(), never()).find(any(), any(), any(), anyString());
verify(ctx, never()).tellFailure(any(), any(Throwable.class)); verify(ctx, never()).tellFailure(any(), any(Throwable.class));
verify(ctx, never()).enqueueForTellNext(any(), eq(expectedOutput), any(), any()); verify(ctx, never()).enqueueForTellNext(any(), eq(expectedOutput), any(), any());
verify(ctx, never()).ack(any()); verify(ctx, never()).ack(any());
ArgumentCaptor<TbMsg> newMsgCaptor = ArgumentCaptor.forClass(TbMsg.class);
if (SUCCESS.equals(expectedOutput)) { if (SUCCESS.equals(expectedOutput)) {
verify(ctx, times(1)).tellSuccess(newMsgCaptor.capture()); verify(ctx).tellSuccess(eq(msg));
} else { } else {
verify(ctx, times(1)).tellNext(newMsgCaptor.capture(), eq(expectedOutput)); verify(ctx).tellNext(eq(msg), eq(expectedOutput));
} }
var actualMsg = newMsgCaptor.getValue();
assertThat(actualMsg).isNotNull();
assertThat(actualMsg).isSameAs(msg);
assertThat(actualMsg.getType()).isSameAs(msg.getType());
assertThat(actualMsg.getData()).isSameAs(msg.getData());
assertThat(actualMsg.getMetaData()).isEqualTo(msg.getMetaData());
assertThat(actualMsg.getOriginator()).isSameAs(msg.getOriginator());
} }
private TbMsg getOutsideRectangleTbMsg(EntityId entityId) { private TbMsg getOutsideRectangleTbMsg(EntityId entityId) {
@ -250,20 +250,9 @@ class TbGpsGeofencingActionNodeTest {
); );
} }
@ParameterizedTest @Override
@MethodSource protected TbNode getTestNode() {
void givenFromVersionAndConfig_whenUpgrade_thenVerifyHasChangesAndConfig(int givenVersion, String givenConfigStr, boolean hasChanges, String expectedConfigStr) throws TbNodeException { return node;
// GIVEN
JsonNode givenConfig = JacksonUtil.toJsonNode(givenConfigStr);
JsonNode expectedConfig = JacksonUtil.toJsonNode(expectedConfigStr);
// WHEN
TbPair<Boolean, JsonNode> upgradeResult = node.upgrade(givenVersion, givenConfig);
// THEN
assertThat(upgradeResult.getFirst()).isEqualTo(hasChanges);
ObjectNode upgradedConfig = (ObjectNode) upgradeResult.getSecond();
assertThat(upgradedConfig).isEqualTo(expectedConfig);
} }
} }