From 310e53fb23ab539d8c244149629e5ab4ed621a33 Mon Sep 17 00:00:00 2001 From: Sergey Matvienko Date: Tue, 21 Apr 2026 20:13:49 +0200 Subject: [PATCH] Fix flaky DeviceProfileControllerTest invalid-RPC-schema tests Several testSaveProtoDeviceProfileWithInvalidRpcRequestSchema* tests intermittently fail with: org.thingsboard.server.dao.exception.TenantNotFoundException: Tenant with id not found when the tenant created in @Before has not yet been populated in the tenant profile cache by the time the request hits the partition-lookup path (DefaultTenantRoutingInfoService -> TbTenantProfileCache -> TenantService#findTenantById). The underlying request is idempotent (the schema is invalid so it is rejected with 400 regardless of retries), so wrap the doPost + status assertion in Awaitility with Mockito.reset inside the retry block: only the last attempt's invocations are visible to the subsequent verify* assertions. Applies to all testSaveDeviceProfileWithInvalidRpcRequestProtoSchema callers, including the currently-muted testSaveProtoDeviceProfileWithInvalidRpcRequestSchemaRequestIdDateType. --- .../DeviceProfileControllerTest.java | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/application/src/test/java/org/thingsboard/server/controller/DeviceProfileControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/DeviceProfileControllerTest.java index 225757e451..7d88edd73f 100644 --- a/application/src/test/java/org/thingsboard/server/controller/DeviceProfileControllerTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/DeviceProfileControllerTest.java @@ -54,11 +54,13 @@ import org.thingsboard.server.common.data.security.Authority; import org.thingsboard.server.dao.device.DeviceProfileDao; import org.thingsboard.server.dao.exception.DataValidationException; import org.thingsboard.server.dao.service.DaoSqlTest; +import org.awaitility.Awaitility; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; +import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; import static org.assertj.core.api.Assertions.assertThat; @@ -1028,11 +1030,17 @@ public class DeviceProfileControllerTest extends AbstractControllerTest { MqttDeviceProfileTransportConfiguration mqttDeviceProfileTransportConfiguration = this.createMqttDeviceProfileTransportConfiguration(protoTransportPayloadConfiguration, false); DeviceProfile deviceProfile = this.createDeviceProfile("Device Profile", mqttDeviceProfileTransportConfiguration); - Mockito.reset(tbClusterService, auditLogService); - - doPost("/api/deviceProfile", deviceProfile) - .andExpect(status().isBadRequest()) - .andExpect(statusReason(containsString(errorMsg))); + // The request may hit a transient TenantNotFoundException right after the @Before tenant creation + // if the tenant profile cache is not yet warmed up for the newly created tenant. Retry until the + // request returns the expected 400 Bad Request for the invalid schema. Mockito.reset is inside the + // retry loop so the subsequent verify* assertions see only the invocations from the last attempt. + Awaitility.await().atMost(10, TimeUnit.SECONDS).pollInterval(500, TimeUnit.MILLISECONDS) + .ignoreExceptions().untilAsserted(() -> { + Mockito.reset(tbClusterService, auditLogService); + doPost("/api/deviceProfile", deviceProfile) + .andExpect(status().isBadRequest()) + .andExpect(statusReason(containsString(errorMsg))); + }); testNotifyEntityEqualsOneTimeServiceNeverError(deviceProfile, savedTenant.getId(), tenantAdmin.getId(), tenantAdmin.getEmail(), ActionType.ADDED, new DataValidationException(errorMsg));