This is an automated email from the ASF dual-hosted git repository.

lizhimins pushed a commit to branch rocketmq-studio
in repository https://gitbox.apache.org/repos/asf/rocketmq-dashboard.git


The following commit(s) were added to refs/heads/rocketmq-studio by this push:
     new 70be77c5c fix: apply window aggregation to native alert rule tests 
(#6876)
70be77c5c is described below

commit 70be77c5cbc9015fe9c866c8d1bbd3d087d9de32
Author: redyyang <[email protected]>
AuthorDate: Mon Oct 19 18:55:06 2026 +0800

    fix: apply window aggregation to native alert rule tests (#6876)
    
    Verified against `rocketmq-studio` at f81e73a49 before merging: 缺陷仍在(主干 
`server/src/main/java/org/apache/rocketmq/studio/ops/alert/NativeAlertRuleTestService.java:81`
 仍是 `AlertEvaluationResult evaluation = evaluato
    
    merge-tree clean against the current trunk. Merged as-is (squash) per the 
maintainer review of 2026-10-19.
---
 .../ops/alert/NativeAlertEvaluationService.java    |  27 +---
 .../ops/alert/NativeAlertRuleTestService.java      |  11 +-
 .../ops/alert/NativeAlertSampleAggregator.java     |  51 +++++++
 .../ops/alert/NativeAlertRuleTestServiceTest.java  | 153 ++++++++++++++++++++-
 .../tencent/TencentCloudLagFailureScopeTest.java   |   4 +-
 5 files changed, 209 insertions(+), 37 deletions(-)

diff --git 
a/server/src/main/java/org/apache/rocketmq/studio/ops/alert/NativeAlertEvaluationService.java
 
b/server/src/main/java/org/apache/rocketmq/studio/ops/alert/NativeAlertEvaluationService.java
index b927b9fa0..fd490ea5a 100644
--- 
a/server/src/main/java/org/apache/rocketmq/studio/ops/alert/NativeAlertEvaluationService.java
+++ 
b/server/src/main/java/org/apache/rocketmq/studio/ops/alert/NativeAlertEvaluationService.java
@@ -17,7 +17,6 @@
 package org.apache.rocketmq.studio.ops.alert;
 
 import lombok.RequiredArgsConstructor;
-import org.apache.rocketmq.studio.cluster.metrics.MetricAvailability;
 import org.apache.rocketmq.studio.cluster.metrics.MetricSample;
 import org.apache.rocketmq.studio.cluster.metrics.MetricSnapshotRepository;
 import org.apache.rocketmq.studio.common.domain.enums.AlertLevel;
@@ -26,11 +25,8 @@ import 
org.springframework.transaction.annotation.Propagation;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.util.StringUtils;
 
-import java.time.Duration;
 import java.time.LocalDateTime;
 import java.time.ZoneOffset;
-import java.util.List;
-import java.util.Locale;
 import java.util.Map;
 import java.util.Optional;
 import java.util.TreeMap;
@@ -53,7 +49,7 @@ public class NativeAlertEvaluationService {
 
     @Transactional(propagation = Propagation.REQUIRES_NEW)
     public void evaluate(AlertRuleVO rule, MetricSample sample) {
-        MetricSample evaluatedSample = aggregate(rule, sample);
+        MetricSample evaluatedSample = 
NativeAlertSampleAggregator.aggregate(rule, sample, snapshotRepository);
         AlertEvaluationResult evaluation = evaluator.evaluate(rule, 
evaluatedSample);
         if (!evaluation.matches()) {
             return;
@@ -102,27 +98,6 @@ public class NativeAlertEvaluationService {
         }
     }
 
-    /** Reads the optional snapshot window inside this evaluation's 
independent transaction. */
-    private MetricSample aggregate(AlertRuleVO rule, MetricSample sample) {
-        if (sample.availability() != MetricAvailability.AVAILABLE || 
rule.getWindowSeconds() <= 0) {
-            return sample;
-        }
-        List<MetricSample> window = snapshotRepository.findRecent(sample,
-                
sample.collectedAt().minus(Duration.ofSeconds(rule.getWindowSeconds())));
-        if (window.isEmpty()) {
-            return sample;
-        }
-        double value = switch (rule.getAggregation() == null ? "LAST" : 
rule.getAggregation().toUpperCase(Locale.ROOT)) {
-            case "MAX" -> window.stream().mapToDouble(item -> 
item.value()).max().orElse(sample.value());
-            case "MIN" -> window.stream().mapToDouble(item -> 
item.value()).min().orElse(sample.value());
-            case "AVG" -> window.stream().mapToDouble(item -> 
item.value()).average().orElse(sample.value());
-            case "SUM" -> window.stream().mapToDouble(item -> 
item.value()).sum();
-            default -> window.get(window.size() - 1).value();
-        };
-        return new MetricSample(sample.metricKey(), sample.domain(), 
sample.instanceId(), sample.clusterId(),
-                sample.labels(), value, MetricAvailability.AVAILABLE, 
sample.collectedAt());
-    }
-
     private void applyNotificationSuppression(SystemAlertVO event, AlertDomain 
domain,
             AlertStateTransition transition) {
         if (!shouldSuppress(domain, transition)) {
diff --git 
a/server/src/main/java/org/apache/rocketmq/studio/ops/alert/NativeAlertRuleTestService.java
 
b/server/src/main/java/org/apache/rocketmq/studio/ops/alert/NativeAlertRuleTestService.java
index dbe556b78..55ad850ba 100644
--- 
a/server/src/main/java/org/apache/rocketmq/studio/ops/alert/NativeAlertRuleTestService.java
+++ 
b/server/src/main/java/org/apache/rocketmq/studio/ops/alert/NativeAlertRuleTestService.java
@@ -21,6 +21,7 @@ import lombok.extern.slf4j.Slf4j;
 import org.apache.rocketmq.studio.cluster.metrics.BusinessMetricsCollector;
 import org.apache.rocketmq.studio.cluster.metrics.ClusterMetricsCollector;
 import org.apache.rocketmq.studio.cluster.metrics.MetricSample;
+import org.apache.rocketmq.studio.cluster.metrics.MetricSnapshotRepository;
 import org.apache.rocketmq.studio.common.exception.BusinessException;
 import org.apache.rocketmq.studio.instance.InstanceRepository;
 import org.apache.rocketmq.studio.instance.InstanceVO;
@@ -39,6 +40,7 @@ public class NativeAlertRuleTestService {
     private final List<ClusterMetricsCollector> clusterCollectors;
     private final List<BusinessMetricsCollector> businessCollectors;
     private final AlertRuleEvaluator evaluator;
+    private final MetricSnapshotRepository snapshotRepository;
 
     public AlertRuleTestResultVO test(AlertRuleVO rule) {
         normalizeRule(rule);
@@ -78,11 +80,12 @@ public class NativeAlertRuleTestService {
                 .filter(sample -> rule.getMetric().equals(sample.metricKey()))
                 .filter(sample -> NativeAlertRuleScopeMatcher.matches(rule, 
sample))
                 .map(sample -> {
-                    AlertEvaluationResult evaluation = 
evaluator.evaluate(rule, sample);
-                    return 
AlertRuleTestResultVO.Sample.builder().labels(sample.labels())
-                            
.availability(sample.availability().name()).currentValue(evaluation.currentValue())
+                    MetricSample evaluatedSample = 
NativeAlertSampleAggregator.aggregate(rule, sample, snapshotRepository);
+                    AlertEvaluationResult evaluation = 
evaluator.evaluate(rule, evaluatedSample);
+                    return 
AlertRuleTestResultVO.Sample.builder().labels(evaluatedSample.labels())
+                            
.availability(evaluatedSample.availability().name()).currentValue(evaluation.currentValue())
                             .conditionMet(evaluation.conditionMet())
-                            
.unavailableReason(sample.unavailableReason()).build();
+                            
.unavailableReason(evaluatedSample.unavailableReason()).build();
                 }).toList()).build();
     }
 
diff --git 
a/server/src/main/java/org/apache/rocketmq/studio/ops/alert/NativeAlertSampleAggregator.java
 
b/server/src/main/java/org/apache/rocketmq/studio/ops/alert/NativeAlertSampleAggregator.java
new file mode 100644
index 000000000..2cea9f0ad
--- /dev/null
+++ 
b/server/src/main/java/org/apache/rocketmq/studio/ops/alert/NativeAlertSampleAggregator.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.rocketmq.studio.ops.alert;
+
+import org.apache.rocketmq.studio.cluster.metrics.MetricAvailability;
+import org.apache.rocketmq.studio.cluster.metrics.MetricSample;
+import org.apache.rocketmq.studio.cluster.metrics.MetricSnapshotRepository;
+
+import java.time.Duration;
+import java.util.List;
+import java.util.Locale;
+
+/** Applies the same stored snapshot window to live evaluations and read-only 
rule tests. */
+final class NativeAlertSampleAggregator {
+    private NativeAlertSampleAggregator() {
+    }
+
+    static MetricSample aggregate(AlertRuleVO rule, MetricSample sample, 
MetricSnapshotRepository snapshots) {
+        if (sample.availability() != MetricAvailability.AVAILABLE || 
rule.getWindowSeconds() <= 0) {
+            return sample;
+        }
+        List<MetricSample> window = snapshots.findRecent(sample,
+                
sample.collectedAt().minus(Duration.ofSeconds(rule.getWindowSeconds())));
+        if (window.isEmpty()) {
+            return sample;
+        }
+        double value = switch (rule.getAggregation() == null ? "LAST" : 
rule.getAggregation().toUpperCase(Locale.ROOT)) {
+            case "MAX" -> window.stream().mapToDouble(item -> 
item.value()).max().orElse(sample.value());
+            case "MIN" -> window.stream().mapToDouble(item -> 
item.value()).min().orElse(sample.value());
+            case "AVG" -> window.stream().mapToDouble(item -> 
item.value()).average().orElse(sample.value());
+            case "SUM" -> window.stream().mapToDouble(item -> 
item.value()).sum();
+            default -> window.get(window.size() - 1).value();
+        };
+        return new MetricSample(sample.metricKey(), sample.domain(), 
sample.instanceId(), sample.clusterId(),
+                sample.labels(), value, MetricAvailability.AVAILABLE, 
sample.collectedAt());
+    }
+}
diff --git 
a/server/src/test/java/org/apache/rocketmq/studio/ops/alert/NativeAlertRuleTestServiceTest.java
 
b/server/src/test/java/org/apache/rocketmq/studio/ops/alert/NativeAlertRuleTestServiceTest.java
index 12cf45bfc..d9ca2eed5 100644
--- 
a/server/src/test/java/org/apache/rocketmq/studio/ops/alert/NativeAlertRuleTestServiceTest.java
+++ 
b/server/src/test/java/org/apache/rocketmq/studio/ops/alert/NativeAlertRuleTestServiceTest.java
@@ -17,12 +17,18 @@
 package org.apache.rocketmq.studio.ops.alert;
 
 import org.apache.rocketmq.studio.cluster.metrics.BusinessMetricsCollector;
-import org.apache.rocketmq.studio.common.exception.BusinessException;
+import org.apache.rocketmq.studio.cluster.metrics.ClusterMetricsCollector;
 import org.apache.rocketmq.studio.cluster.metrics.MetricAvailability;
 import org.apache.rocketmq.studio.cluster.metrics.MetricSample;
+import org.apache.rocketmq.studio.cluster.metrics.MetricSnapshotRepository;
+import org.apache.rocketmq.studio.common.exception.BusinessException;
 import org.apache.rocketmq.studio.instance.InstanceRepository;
 import org.apache.rocketmq.studio.instance.InstanceVO;
 import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.CsvSource;
+import org.junit.jupiter.params.provider.EnumSource;
+import org.junit.jupiter.params.provider.ValueSource;
 
 import java.time.Instant;
 import java.util.List;
@@ -31,10 +37,15 @@ import java.util.Optional;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.assertj.core.api.Assertions.within;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoInteractions;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
 import static org.mockito.Mockito.when;
 
 class NativeAlertRuleTestServiceTest {
+    private final MetricSnapshotRepository snapshots = 
mock(MetricSnapshotRepository.class);
 
     @Test
     void 
evaluatesOnlyTheSelectedConsumerGroupWithoutPersistingEvenWhenTheRuleIsNotYetEnabledTest()
 {
@@ -48,7 +59,7 @@ class NativeAlertRuleTestServiceTest {
                 
.instanceId("local").consumerGroup("orders").operator(">").threshold(10).enabled(false).build();
 
         AlertRuleTestResultVO result = new 
NativeAlertRuleTestService(instances, List.of(), List.of(collector),
-                new AlertRuleEvaluator()).test(rule);
+                new AlertRuleEvaluator(), snapshots).test(rule);
 
         assertThat(result.samples()).singleElement().satisfies(sample -> {
             assertThat(sample.labels()).containsEntry("consumerGroup", 
"orders");
@@ -72,7 +83,7 @@ class NativeAlertRuleTestServiceTest {
                 
.instanceId("local").consumerGroup("orders").operator(">").threshold(10).build();
 
         AlertRuleTestResultVO result = new 
NativeAlertRuleTestService(instances, List.of(), List.of(collector),
-                new AlertRuleEvaluator()).test(rule);
+                new AlertRuleEvaluator(), snapshots).test(rule);
 
         assertThat(result.samples()).singleElement().satisfies(sample -> {
             assertThat(sample.currentValue()).isEqualTo(20);
@@ -96,7 +107,7 @@ class NativeAlertRuleTestServiceTest {
                 .build();
 
         AlertRuleTestResultVO result = new 
NativeAlertRuleTestService(instances, List.of(), List.of(collector),
-                new AlertRuleEvaluator()).test(rule);
+                new AlertRuleEvaluator(), snapshots).test(rule);
 
         assertThat(result.samples()).singleElement().satisfies(sample -> {
             assertThat(sample.currentValue()).isEqualTo(20);
@@ -119,7 +130,7 @@ class NativeAlertRuleTestServiceTest {
                 
.instanceId("local").consumerGroup("orders").operator(">").threshold(10).build();
 
         AlertRuleTestResultVO result = new 
NativeAlertRuleTestService(instances, List.of(),
-                List.of(failing, healthy), new 
AlertRuleEvaluator()).test(rule);
+                List.of(failing, healthy), new AlertRuleEvaluator(), 
snapshots).test(rule);
 
         assertThat(result.samples()).singleElement()
                 .satisfies(sample -> 
assertThat(sample.currentValue()).isEqualTo(20));
@@ -137,16 +148,146 @@ class NativeAlertRuleTestServiceTest {
                 .operator(">").threshold(10).build();
 
         assertThatThrownBy(() -> new NativeAlertRuleTestService(instances, 
List.of(), List.of(collector),
-                new AlertRuleEvaluator()).test(rule))
+                new AlertRuleEvaluator(), snapshots).test(rule))
                 .isInstanceOf(BusinessException.class)
                 .hasMessage("metric is required")
                 .satisfies(error -> assertThat(((BusinessException) 
error).getCode()).isEqualTo(400));
     }
 
+    @ParameterizedTest
+    @CsvSource(value = {"AVG, 336.6666666667, true", "MAX, 500, true", "MIN, 
10, false", "SUM, 1010, true",
+        "LAST, 10, false", "NULL, 10, false", "avg, 336.6666666667, true"}, 
nullValues = "NULL")
+    void aggregatesTheStoredWindowBeforeEvaluatingARuleTest(String 
aggregation, double expectedValue,
+            boolean expectedCondition) {
+        MetricSample current = sample("orders", 10);
+        when(snapshots.findRecent(current, 
current.collectedAt().minusSeconds(300)))
+                .thenReturn(List.of(sample("orders", 500, 
current.collectedAt().minusSeconds(120)),
+                        sample("orders", 500, 
current.collectedAt().minusSeconds(60)), current));
+        AlertRuleVO rule = 
AlertRuleVO.builder().domain(AlertDomain.BUSINESS).metric("consumer.lag.total")
+                
.instanceId("local").consumerGroup("orders").operator(">").threshold(100)
+                
.aggregation(aggregation).windowSeconds(300).enabled(false).build();
+
+        AlertRuleTestResultVO result = testBusinessRule(rule, current, 
sample("payments", 1000),
+                sample("consumer.delay.seconds", "orders", 1000));
+
+        assertThat(result.samples()).singleElement().satisfies(sample -> {
+            assertThat(sample.labels()).containsEntry("consumerGroup", 
"orders");
+            assertThat(sample.availability()).isEqualTo("AVAILABLE");
+            assertThat(sample.currentValue()).isCloseTo(expectedValue, 
within(0.000001));
+            assertThat(sample.conditionMet()).isEqualTo(expectedCondition);
+        });
+        verify(snapshots).findRecent(current, 
current.collectedAt().minusSeconds(300));
+        verifyNoMoreInteractions(snapshots);
+    }
+
+    @Test
+    void aggregatesClusterMetricWindowsBeforeEvaluatingARuleTest() {
+        InstanceRepository instances = mock(InstanceRepository.class);
+        ClusterMetricsCollector collector = 
mock(ClusterMetricsCollector.class);
+        InstanceVO instance = InstanceVO.builder().name("local").build();
+        
when(instances.findByIdentifier("local")).thenReturn(Optional.of(instance));
+        when(collector.supports(instance)).thenReturn(true);
+        MetricSample current = new MetricSample("broker.disk.usage_ratio", 
AlertDomain.CLUSTER, "local", "cluster-a",
+                Map.of("brokerName", "broker-a"), 0.1, 
MetricAvailability.AVAILABLE, Instant.now());
+        MetricSample previous = new MetricSample(current.metricKey(), 
current.domain(), current.instanceId(),
+                current.clusterId(), current.labels(), 0.9, 
MetricAvailability.AVAILABLE,
+                current.collectedAt().minusSeconds(60));
+        when(collector.collect(instance)).thenReturn(List.of(current));
+        when(snapshots.findRecent(current, 
current.collectedAt().minusSeconds(300)))
+                .thenReturn(List.of(previous, current));
+        AlertRuleVO rule = 
AlertRuleVO.builder().domain(AlertDomain.CLUSTER).metric(current.metricKey())
+                
.instanceId("local").brokerName("broker-a").operator(">").threshold(0.8)
+                .aggregation("MAX").windowSeconds(300).build();
+
+        AlertRuleTestResultVO result = new 
NativeAlertRuleTestService(instances, List.of(collector), List.of(),
+                new AlertRuleEvaluator(), snapshots).test(rule);
+
+        assertThat(result.samples()).singleElement().satisfies(sample -> {
+            assertThat(sample.currentValue()).isEqualTo(0.9);
+            assertThat(sample.conditionMet()).isTrue();
+        });
+        verify(snapshots).findRecent(current, 
current.collectedAt().minusSeconds(300));
+        verifyNoMoreInteractions(snapshots);
+    }
+
+    @ParameterizedTest
+    @ValueSource(ints = {0, -1})
+    void 
evaluatesCurrentSampleWithoutReadingSnapshotsWhenWindowIsDisabledTest(int 
windowSeconds) {
+        AlertRuleVO rule = 
AlertRuleVO.builder().metric("consumer.lag.total").instanceId("local")
+                
.operator(">").threshold(100).aggregation("AVG").windowSeconds(windowSeconds).build();
+
+        AlertRuleTestResultVO result = testBusinessRule(rule, sample("orders", 
10));
+
+        assertThat(result.samples()).singleElement().satisfies(sample -> {
+            assertThat(sample.currentValue()).isEqualTo(10);
+            assertThat(sample.conditionMet()).isFalse();
+        });
+        verifyNoInteractions(snapshots);
+    }
+
+    @Test
+    void fallsBackToCurrentSampleWhenStoredWindowIsEmptyTest() {
+        MetricSample current = sample("orders", 10);
+        when(snapshots.findRecent(current, 
current.collectedAt().minusSeconds(300))).thenReturn(List.of());
+        AlertRuleVO rule = 
AlertRuleVO.builder().metric("consumer.lag.total").instanceId("local")
+                
.operator(">").threshold(5).aggregation("AVG").windowSeconds(300).build();
+
+        AlertRuleTestResultVO result = testBusinessRule(rule, current);
+
+        assertThat(result.samples()).singleElement().satisfies(sample -> {
+            assertThat(sample.currentValue()).isEqualTo(10);
+            assertThat(sample.conditionMet()).isTrue();
+        });
+        verify(snapshots).findRecent(current, 
current.collectedAt().minusSeconds(300));
+        verifyNoMoreInteractions(snapshots);
+    }
+
+    @ParameterizedTest
+    @EnumSource(value = MetricAvailability.class, names = {"UNAVAILABLE", 
"UNSUPPORTED", "STALE"})
+    void 
preservesUnavailableSampleInsteadOfReplacingItWithHistoricalValuesTest(MetricAvailability
 availability) {
+        InstanceRepository instances = mock(InstanceRepository.class);
+        ClusterMetricsCollector collector = 
mock(ClusterMetricsCollector.class);
+        InstanceVO instance = InstanceVO.builder().name("local").build();
+        
when(instances.findByIdentifier("local")).thenReturn(Optional.of(instance));
+        when(collector.supports(instance)).thenReturn(true);
+        MetricSample unavailable = new MetricSample("broker.availability", 
AlertDomain.CLUSTER, "local", null,
+                Map.of("brokerName", "broker-a"), null, availability, 
Instant.now(), "collection failed");
+        when(collector.collect(instance)).thenReturn(List.of(unavailable));
+        AlertRuleVO rule = 
AlertRuleVO.builder().domain(AlertDomain.CLUSTER).metric(unavailable.metricKey())
+                
.instanceId("local").operator("UNAVAILABLE").aggregation("AVG").windowSeconds(300).build();
+
+        AlertRuleTestResultVO result = new 
NativeAlertRuleTestService(instances, List.of(collector), List.of(),
+                new AlertRuleEvaluator(), snapshots).test(rule);
+
+        assertThat(result.samples()).singleElement().satisfies(sample -> {
+            assertThat(sample.availability()).isEqualTo(availability.name());
+            assertThat(sample.currentValue()).isNull();
+            assertThat(sample.conditionMet()).isEqualTo(availability == 
MetricAvailability.UNAVAILABLE);
+            assertThat(sample.unavailableReason()).isEqualTo("collection 
failed");
+        });
+        verifyNoInteractions(snapshots);
+    }
+
+    private AlertRuleTestResultVO testBusinessRule(AlertRuleVO rule, 
MetricSample... samples) {
+        InstanceRepository instances = mock(InstanceRepository.class);
+        BusinessMetricsCollector collector = 
mock(BusinessMetricsCollector.class);
+        InstanceVO instance = InstanceVO.builder().name("local").build();
+        
when(instances.findByIdentifier("local")).thenReturn(Optional.of(instance));
+        when(collector.supports(instance)).thenReturn(true);
+        when(collector.collect(instance)).thenReturn(List.of(samples));
+        return new NativeAlertRuleTestService(instances, List.of(), 
List.of(collector),
+                new AlertRuleEvaluator(), snapshots).test(rule);
+    }
+
     private static MetricSample sample(String group, double value) {
         return sample("consumer.lag.total", group, value);
     }
 
+    private static MetricSample sample(String group, double value, Instant 
collectedAt) {
+        return new MetricSample("consumer.lag.total", AlertDomain.BUSINESS, 
"local", null,
+                Map.of("consumerGroup", group), value, 
MetricAvailability.AVAILABLE, collectedAt);
+    }
+
     private static MetricSample sample(String metric, String group, double 
value) {
         return new MetricSample(metric, AlertDomain.BUSINESS, "local", null,
                 Map.of("consumerGroup", group), value, 
MetricAvailability.AVAILABLE, Instant.now());
diff --git 
a/server/src/test/java/org/apache/rocketmq/studio/provider/tencent/TencentCloudLagFailureScopeTest.java
 
b/server/src/test/java/org/apache/rocketmq/studio/provider/tencent/TencentCloudLagFailureScopeTest.java
index 454a3121e..afbdfadc0 100644
--- 
a/server/src/test/java/org/apache/rocketmq/studio/provider/tencent/TencentCloudLagFailureScopeTest.java
+++ 
b/server/src/test/java/org/apache/rocketmq/studio/provider/tencent/TencentCloudLagFailureScopeTest.java
@@ -22,6 +22,7 @@ import 
com.tencentcloudapi.trocket.v20230308.models.DescribeConsumerGroupListRes
 import 
com.tencentcloudapi.trocket.v20230308.models.DescribeTopicListByGroupResponse;
 import com.tencentcloudapi.trocket.v20230308.models.SubscriptionData;
 import org.apache.rocketmq.studio.cluster.metrics.MetricAvailability;
+import org.apache.rocketmq.studio.cluster.metrics.MetricSnapshotRepository;
 import 
org.apache.rocketmq.studio.cluster.metrics.collectors.CloudRocketMqBusinessMetricsCollector;
 import org.apache.rocketmq.studio.common.domain.enums.InstanceVendor;
 import org.apache.rocketmq.studio.common.exception.BusinessException;
@@ -146,6 +147,7 @@ class TencentCloudLagFailureScopeTest {
         InstanceProviderRegistry registry = 
mock(InstanceProviderRegistry.class);
         
when(registry.byInstanceId("tencent-prod")).thenReturn(Optional.of(provider));
         return new NativeAlertRuleTestService(instances, List.of(),
-                List.of(new CloudRocketMqBusinessMetricsCollector(registry)), 
new AlertRuleEvaluator());
+                List.of(new CloudRocketMqBusinessMetricsCollector(registry)), 
new AlertRuleEvaluator(),
+                mock(MetricSnapshotRepository.class));
     }
 }

Reply via email to