You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@unomi.apache.org by sh...@apache.org on 2026/06/29 09:45:09 UTC
(unomi) 01/01: UNOMI-881: Harden GoalsServiceImplTest against full-suite flakiness
This is an automated email from the ASF dual-hosted git repository.
sergehuber pushed a commit to branch UNOMI-881-goals-test-flake
in repository https://gitbox.apache.org/repos/asf/unomi.git
commit ccc7bf19138e0d1e4bd4170202f6c99199303f70
Author: Serge Huber <sh...@apache.org>
AuthorDate: Mon Jun 29 11:44:58 2026 +0200
UNOMI-881: Harden GoalsServiceImplTest against full-suite flakiness
Align teardown with RulesServiceImplTest (shutdown event admin, rules service, scheduler), clear execution context between tests, and run nested-condition setup under executeAsSystem so system-tenant condition types resolve reliably in CI.
---
.../services/impl/goals/GoalsServiceImplTest.java | 89 +++++++++++++---------
1 file changed, 53 insertions(+), 36 deletions(-)
diff --git a/services/src/test/java/org/apache/unomi/services/impl/goals/GoalsServiceImplTest.java b/services/src/test/java/org/apache/unomi/services/impl/goals/GoalsServiceImplTest.java
index 54d41ecd8..2884b4a60 100644
--- a/services/src/test/java/org/apache/unomi/services/impl/goals/GoalsServiceImplTest.java
+++ b/services/src/test/java/org/apache/unomi/services/impl/goals/GoalsServiceImplTest.java
@@ -19,8 +19,8 @@ package org.apache.unomi.services.impl.goals;
import org.apache.unomi.api.Metadata;
import org.apache.unomi.api.actions.ActionType;
import org.apache.unomi.api.conditions.Condition;
+import org.apache.unomi.api.conditions.ConditionType;
import org.apache.unomi.api.goals.Goal;
-import org.apache.unomi.api.services.ConditionValidationService;
import org.apache.unomi.api.services.EventService;
import org.apache.unomi.api.services.RulesService;
import org.apache.unomi.api.services.SchedulerService;
@@ -36,6 +36,7 @@ import org.apache.unomi.services.impl.TestTenantService;
import org.apache.unomi.services.impl.cache.MultiTypeCacheServiceImpl;
import org.apache.unomi.services.impl.definitions.DefinitionsServiceImpl;
import org.apache.unomi.services.impl.events.EventServiceImpl;
+import org.apache.unomi.services.impl.rules.RulesServiceImpl;
import org.apache.unomi.services.impl.rules.TestActionExecutorDispatcher;
import org.apache.unomi.services.impl.scheduler.SchedulerServiceImpl;
import org.apache.unomi.tracing.api.TracerService;
@@ -52,6 +53,8 @@ import org.osgi.framework.BundleContext;
import java.io.IOException;
import java.util.*;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
@ExtendWith(MockitoExtension.class)
@MockitoSettings(strictness = Strictness.LENIENT)
public class GoalsServiceImplTest {
@@ -66,6 +69,7 @@ public class GoalsServiceImplTest {
private EventServiceImpl eventService;
private SchedulerService schedulerService;
private MultiTypeCacheServiceImpl multiTypeCacheService;
+ private TestEventAdmin testEventAdmin;
@Mock
private BundleContext bundleContext;
@@ -74,6 +78,7 @@ public class GoalsServiceImplTest {
TracerService tracerService = TestHelper.createTracerService();
tenantService = new TestTenantService();
+ TestHelper.setupCommonTestData(tenantService);
tenantService.setCurrentTenantId("test-tenant");
ConditionEvaluatorDispatcher conditionEvaluatorDispatcher = TestConditionEvaluators.createDispatcher();
securityService = TestHelper.createSecurityService();
@@ -90,7 +95,7 @@ public class GoalsServiceImplTest {
TestHelper.createDefinitionServiceWithEventAdmin(persistenceService, bundleContext, schedulerService,
multiTypeCacheService, executionContextManager, tenantService);
definitionsService = servicePair.getKey();
- TestEventAdmin testEventAdmin = servicePair.getValue();
+ testEventAdmin = servicePair.getValue();
// Inject definitionsService into the dispatcher
TestHelper.injectDefinitionsServiceIntoDispatcher(conditionEvaluatorDispatcher, definitionsService);
@@ -144,14 +149,21 @@ public class GoalsServiceImplTest {
@AfterEach
public void tearDown() throws Exception {
- // Shutdown TestEventAdmin if it exists (created via createDefinitionServiceWithEventAdmin)
- // Note: TestEventAdmin is created internally by createDefinitionService, but we only have access
- // to it when using createDefinitionServiceWithEventAdmin. For now, we rely on JVM cleanup.
-
- // Stop scheduler service
- if (schedulerService != null && schedulerService instanceof SchedulerServiceImpl) {
+ if (testEventAdmin != null) {
+ testEventAdmin.shutdown();
+ }
+ if (rulesService != null) {
+ ((RulesServiceImpl) rulesService).preDestroy();
+ }
+ if (eventService != null && rulesService != null) {
+ eventService.removeEventListenerService((RulesServiceImpl) rulesService);
+ }
+ if (schedulerService instanceof SchedulerServiceImpl) {
((SchedulerServiceImpl) schedulerService).preDestroy();
}
+ if (executionContextManager != null) {
+ executionContextManager.setCurrentContext(null);
+ }
// Clear cache by clearing each tenant
if (multiTypeCacheService != null) {
@@ -181,6 +193,7 @@ public class GoalsServiceImplTest {
eventService = null;
schedulerService = null;
multiTypeCacheService = null;
+ testEventAdmin = null;
bundleContext = null;
}
@@ -247,33 +260,37 @@ public class GoalsServiceImplTest {
@Test
public void testSetGoalWithNestedConditions() {
- // Create a goal with nested conditions
- Goal goal = new Goal();
- goal.setMetadata(new Metadata());
- goal.getMetadata().setId("testGoal");
- goal.getMetadata().setEnabled(true);
-
- // Create parent condition
- Condition parentCondition = new Condition();
- parentCondition.setConditionTypeId("booleanCondition");
- parentCondition.setConditionType(definitionsService.getConditionType("booleanCondition"));
- parentCondition.setParameter("operator", "and");
-
- // Create child condition
- Condition childCondition = new Condition();
- childCondition.setConditionTypeId("profilePropertyCondition");
- childCondition.setConditionType(definitionsService.getConditionType("profilePropertyCondition"));
- childCondition.setParameter("propertyName", "profileProperty");
- childCondition.setParameter("comparisonOperator", "exists");
-
- // Set up nested structure
- List<Condition> subConditions = new ArrayList<>();
- subConditions.add(childCondition);
- parentCondition.setParameter("subConditions", subConditions);
-
- goal.setStartEvent(parentCondition);
-
- // Should not throw any exceptions
- goalsService.setGoal(goal);
+ executionContextManager.executeAsSystem(() -> {
+ Goal goal = new Goal();
+ Metadata metadata = new Metadata();
+ metadata.setId("testGoal");
+ metadata.setEnabled(true);
+ goal.setMetadata(metadata);
+ goal.setItemId("testGoal");
+
+ ConditionType booleanConditionType = definitionsService.getConditionType("booleanCondition");
+ assertNotNull(booleanConditionType, "Boolean condition type should exist");
+ ConditionType profilePropertyConditionType = definitionsService.getConditionType("profilePropertyCondition");
+ assertNotNull(profilePropertyConditionType, "Profile property condition type should exist");
+
+ Condition parentCondition = new Condition();
+ parentCondition.setConditionTypeId("booleanCondition");
+ parentCondition.setConditionType(booleanConditionType);
+ parentCondition.setParameter("operator", "and");
+
+ Condition childCondition = new Condition();
+ childCondition.setConditionTypeId("profilePropertyCondition");
+ childCondition.setConditionType(profilePropertyConditionType);
+ childCondition.setParameter("propertyName", "profileProperty");
+ childCondition.setParameter("comparisonOperator", "exists");
+
+ List<Condition> subConditions = new ArrayList<>();
+ subConditions.add(childCondition);
+ parentCondition.setParameter("subConditions", subConditions);
+
+ goal.setStartEvent(parentCondition);
+ goalsService.setGoal(goal);
+ return null;
+ });
}
}