test(alerting): decentralize @MockBean + add SpringContextSmokeIT (follow-up to #141) #142
@@ -1,10 +1,7 @@
|
|||||||
package com.cameleer.server.app;
|
package com.cameleer.server.app;
|
||||||
|
|
||||||
import com.cameleer.server.app.search.ClickHouseSearchIndex;
|
|
||||||
import com.cameleer.server.core.agent.AgentRegistryService;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.boot.test.context.SpringBootTest;
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
import org.springframework.boot.test.mock.mockito.MockBean;
|
|
||||||
import org.springframework.jdbc.core.JdbcTemplate;
|
import org.springframework.jdbc.core.JdbcTemplate;
|
||||||
import org.springframework.test.context.ActiveProfiles;
|
import org.springframework.test.context.ActiveProfiles;
|
||||||
import org.springframework.test.context.DynamicPropertyRegistry;
|
import org.springframework.test.context.DynamicPropertyRegistry;
|
||||||
@@ -17,12 +14,6 @@ import org.testcontainers.containers.PostgreSQLContainer;
|
|||||||
@ActiveProfiles("test")
|
@ActiveProfiles("test")
|
||||||
public abstract class AbstractPostgresIT {
|
public abstract class AbstractPostgresIT {
|
||||||
|
|
||||||
// Mocked infrastructure beans required by the full application context.
|
|
||||||
// ClickHouseSearchIndex is not available in test without explicit ClickHouse wiring,
|
|
||||||
// and AgentRegistryService requires in-memory state that tests manage directly.
|
|
||||||
@MockBean(name = "clickHouseSearchIndex") protected ClickHouseSearchIndex clickHouseSearchIndex;
|
|
||||||
@MockBean protected AgentRegistryService agentRegistryService;
|
|
||||||
|
|
||||||
static final PostgreSQLContainer<?> postgres;
|
static final PostgreSQLContainer<?> postgres;
|
||||||
static final ClickHouseContainer clickhouse;
|
static final ClickHouseContainer clickhouse;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package com.cameleer.server.app;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Asserts the full production Spring context loads without any @MockBean
|
||||||
|
* replacements. This is the regression test for the #141 crashloop — declared
|
||||||
|
* bean types must match autowire expectations end-to-end.
|
||||||
|
*/
|
||||||
|
class SpringContextSmokeIT extends AbstractPostgresIT {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void contextLoads() {
|
||||||
|
// no-op: @SpringBootTest refresh is the assertion
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,6 +3,7 @@ package com.cameleer.server.app.alerting;
|
|||||||
import com.cameleer.server.app.AbstractPostgresIT;
|
import com.cameleer.server.app.AbstractPostgresIT;
|
||||||
import com.cameleer.server.app.TestSecurityHelper;
|
import com.cameleer.server.app.TestSecurityHelper;
|
||||||
import com.cameleer.server.app.search.ClickHouseLogStore;
|
import com.cameleer.server.app.search.ClickHouseLogStore;
|
||||||
|
import com.cameleer.server.core.agent.AgentRegistryService;
|
||||||
import com.cameleer.server.core.alerting.*;
|
import com.cameleer.server.core.alerting.*;
|
||||||
import com.fasterxml.jackson.databind.JsonNode;
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
@@ -26,7 +27,7 @@ import static org.mockito.Mockito.when;
|
|||||||
*/
|
*/
|
||||||
class AlertingEnvIsolationIT extends AbstractPostgresIT {
|
class AlertingEnvIsolationIT extends AbstractPostgresIT {
|
||||||
|
|
||||||
// AbstractPostgresIT already declares clickHouseSearchIndex + agentRegistryService mocks.
|
@MockBean AgentRegistryService agentRegistryService;
|
||||||
@MockBean(name = "clickHouseLogStore") ClickHouseLogStore clickHouseLogStore;
|
@MockBean(name = "clickHouseLogStore") ClickHouseLogStore clickHouseLogStore;
|
||||||
|
|
||||||
@Autowired private TestRestTemplate restTemplate;
|
@Autowired private TestRestTemplate restTemplate;
|
||||||
|
|||||||
@@ -49,8 +49,6 @@ import static org.assertj.core.api.Assertions.assertThat;
|
|||||||
@TestInstance(Lifecycle.PER_CLASS)
|
@TestInstance(Lifecycle.PER_CLASS)
|
||||||
class AlertingFullLifecycleIT extends AbstractPostgresIT {
|
class AlertingFullLifecycleIT extends AbstractPostgresIT {
|
||||||
|
|
||||||
// AbstractPostgresIT already declares clickHouseSearchIndex + agentRegistryService mocks.
|
|
||||||
|
|
||||||
// Replace the alertingClock bean so we can control time in re-notify test
|
// Replace the alertingClock bean so we can control time in re-notify test
|
||||||
@MockBean(name = "alertingClock") Clock alertingClock;
|
@MockBean(name = "alertingClock") Clock alertingClock;
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package com.cameleer.server.app.alerting;
|
|||||||
import com.cameleer.server.app.AbstractPostgresIT;
|
import com.cameleer.server.app.AbstractPostgresIT;
|
||||||
import com.cameleer.server.app.TestSecurityHelper;
|
import com.cameleer.server.app.TestSecurityHelper;
|
||||||
import com.cameleer.server.app.search.ClickHouseLogStore;
|
import com.cameleer.server.app.search.ClickHouseLogStore;
|
||||||
|
import com.cameleer.server.core.agent.AgentRegistryService;
|
||||||
import com.fasterxml.jackson.databind.JsonNode;
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import org.junit.jupiter.api.AfterEach;
|
import org.junit.jupiter.api.AfterEach;
|
||||||
@@ -31,7 +32,7 @@ import static org.mockito.Mockito.when;
|
|||||||
*/
|
*/
|
||||||
class OutboundConnectionAllowedEnvIT extends AbstractPostgresIT {
|
class OutboundConnectionAllowedEnvIT extends AbstractPostgresIT {
|
||||||
|
|
||||||
// AbstractPostgresIT already declares clickHouseSearchIndex + agentRegistryService mocks.
|
@MockBean AgentRegistryService agentRegistryService;
|
||||||
@MockBean(name = "clickHouseLogStore") ClickHouseLogStore clickHouseLogStore;
|
@MockBean(name = "clickHouseLogStore") ClickHouseLogStore clickHouseLogStore;
|
||||||
|
|
||||||
@Autowired private TestRestTemplate restTemplate;
|
@Autowired private TestRestTemplate restTemplate;
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package com.cameleer.server.app.alerting.eval;
|
|||||||
import com.cameleer.server.app.AbstractPostgresIT;
|
import com.cameleer.server.app.AbstractPostgresIT;
|
||||||
import com.cameleer.server.app.search.ClickHouseLogStore;
|
import com.cameleer.server.app.search.ClickHouseLogStore;
|
||||||
import com.cameleer.server.core.agent.AgentInfo;
|
import com.cameleer.server.core.agent.AgentInfo;
|
||||||
|
import com.cameleer.server.core.agent.AgentRegistryService;
|
||||||
import com.cameleer.server.core.agent.AgentState;
|
import com.cameleer.server.core.agent.AgentState;
|
||||||
import com.cameleer.server.core.alerting.*;
|
import com.cameleer.server.core.alerting.*;
|
||||||
import org.junit.jupiter.api.AfterEach;
|
import org.junit.jupiter.api.AfterEach;
|
||||||
@@ -23,19 +24,15 @@ import static org.mockito.Mockito.when;
|
|||||||
* Integration test for {@link AlertEvaluatorJob}.
|
* Integration test for {@link AlertEvaluatorJob}.
|
||||||
* <p>
|
* <p>
|
||||||
* Uses real Postgres (Testcontainers) for the full claim→persist pipeline.
|
* Uses real Postgres (Testcontainers) for the full claim→persist pipeline.
|
||||||
* {@code ClickHouseSearchIndex} and {@code ClickHouseLogStore} are mocked so
|
* {@code ClickHouseLogStore} is mocked so {@code LogPatternEvaluator} wires up
|
||||||
* {@code ExchangeMatchEvaluator} and {@code LogPatternEvaluator} wire up even
|
* without requiring real ClickHouse query behaviour.
|
||||||
* though those concrete types are not directly registered as Spring beans.
|
|
||||||
* {@code AgentRegistryService} is mocked so tests can control which agents
|
* {@code AgentRegistryService} is mocked so tests can control which agents
|
||||||
* are DEAD without depending on in-memory timing.
|
* are DEAD without depending on in-memory timing.
|
||||||
*/
|
*/
|
||||||
class AlertEvaluatorJobIT extends AbstractPostgresIT {
|
class AlertEvaluatorJobIT extends AbstractPostgresIT {
|
||||||
|
|
||||||
// Replace the named beans so ExchangeMatchEvaluator / LogPatternEvaluator can wire their
|
|
||||||
// concrete-type constructor args without duplicating the SearchIndex / LogIndex beans.
|
|
||||||
@MockBean(name = "clickHouseLogStore") ClickHouseLogStore clickHouseLogStore;
|
@MockBean(name = "clickHouseLogStore") ClickHouseLogStore clickHouseLogStore;
|
||||||
|
@MockBean AgentRegistryService agentRegistryService;
|
||||||
// Control agent state per test without timing sensitivity
|
|
||||||
|
|
||||||
@Autowired private AlertEvaluatorJob job;
|
@Autowired private AlertEvaluatorJob job;
|
||||||
@Autowired private AlertRuleRepository ruleRepo;
|
@Autowired private AlertRuleRepository ruleRepo;
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package com.cameleer.server.app.alerting.notify;
|
|||||||
|
|
||||||
import com.cameleer.server.app.AbstractPostgresIT;
|
import com.cameleer.server.app.AbstractPostgresIT;
|
||||||
import com.cameleer.server.app.search.ClickHouseLogStore;
|
import com.cameleer.server.app.search.ClickHouseLogStore;
|
||||||
|
import com.cameleer.server.core.agent.AgentRegistryService;
|
||||||
import com.cameleer.server.core.alerting.*;
|
import com.cameleer.server.core.alerting.*;
|
||||||
import com.cameleer.server.core.http.TrustMode;
|
import com.cameleer.server.core.http.TrustMode;
|
||||||
import com.cameleer.server.core.outbound.OutboundAuth;
|
import com.cameleer.server.core.outbound.OutboundAuth;
|
||||||
@@ -35,6 +36,7 @@ import static org.mockito.Mockito.*;
|
|||||||
class NotificationDispatchJobIT extends AbstractPostgresIT {
|
class NotificationDispatchJobIT extends AbstractPostgresIT {
|
||||||
|
|
||||||
@MockBean(name = "clickHouseLogStore") ClickHouseLogStore clickHouseLogStore;
|
@MockBean(name = "clickHouseLogStore") ClickHouseLogStore clickHouseLogStore;
|
||||||
|
@MockBean AgentRegistryService agentRegistryService;
|
||||||
|
|
||||||
/** Mock the dispatcher — we control outcomes per test. */
|
/** Mock the dispatcher — we control outcomes per test. */
|
||||||
@MockBean WebhookDispatcher webhookDispatcher;
|
@MockBean WebhookDispatcher webhookDispatcher;
|
||||||
|
|||||||
@@ -30,8 +30,6 @@ import static org.assertj.core.api.Assertions.assertThat;
|
|||||||
*/
|
*/
|
||||||
class AlertingRetentionJobIT extends AbstractPostgresIT {
|
class AlertingRetentionJobIT extends AbstractPostgresIT {
|
||||||
|
|
||||||
// AbstractPostgresIT already declares clickHouseSearchIndex + agentRegistryService mocks.
|
|
||||||
// Declare only the additional mock needed by this test.
|
|
||||||
@MockBean(name = "clickHouseLogStore") ClickHouseLogStore clickHouseLogStore;
|
@MockBean(name = "clickHouseLogStore") ClickHouseLogStore clickHouseLogStore;
|
||||||
|
|
||||||
@Autowired private AlertingRetentionJob job;
|
@Autowired private AlertingRetentionJob job;
|
||||||
|
|||||||
Reference in New Issue
Block a user