日志记录提交
This commit is contained in:
@@ -0,0 +1,113 @@
|
||||
package com.baiyue.common.audit;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.apache.rocketmq.spring.core.RocketMQTemplate;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.boot.test.mock.mockito.MockBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
|
||||
import org.springframework.transaction.support.TransactionOperations;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.List;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyLong;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.doThrow;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@SpringJUnitConfig(ReliableAuditDeliveryTest.Config.class)
|
||||
class ReliableAuditDeliveryTest {
|
||||
@MockBean
|
||||
private AuditOutboxRepository repository;
|
||||
@MockBean
|
||||
private RocketMQTemplate rocketMQ;
|
||||
@MockBean
|
||||
private TransactionOperations transactions;
|
||||
@Resource
|
||||
private OutboxAuditSink sink;
|
||||
@Resource
|
||||
private AuditOutboxPublisher publisher;
|
||||
|
||||
@Test
|
||||
void storesEventBeforeDelivery() {
|
||||
AuditEvent event = event("audit-1");
|
||||
org.mockito.Mockito.doAnswer(invocation -> {
|
||||
java.util.function.Consumer<?> callback = invocation.getArgument(0);
|
||||
((java.util.function.Consumer<Object>) callback).accept(null);
|
||||
return null;
|
||||
}).when(transactions).executeWithoutResult(any());
|
||||
|
||||
sink.publish(event);
|
||||
|
||||
verify(repository).append(eq(event), anyString());
|
||||
}
|
||||
|
||||
@Test
|
||||
void marksDeliveredMessageSent() {
|
||||
when(repository.publishableIds(50)).thenReturn(List.of("audit-1"));
|
||||
when(repository.claim("audit-1", "test-owner", 60)).thenReturn(true);
|
||||
when(repository.find("audit-1"))
|
||||
.thenReturn(new AuditOutboxRepository.OutboxRow("audit-1", "{}", 1));
|
||||
|
||||
publisher.publish();
|
||||
|
||||
verify(rocketMQ).syncSend(anyString(), any(Message.class), anyLong());
|
||||
verify(repository).sent("audit-1", "test-owner");
|
||||
}
|
||||
|
||||
@Test
|
||||
void schedulesRetryAfterMqFailure() {
|
||||
when(repository.publishableIds(50)).thenReturn(List.of("audit-2"));
|
||||
when(repository.claim("audit-2", "test-owner", 60)).thenReturn(true);
|
||||
when(repository.find("audit-2"))
|
||||
.thenReturn(new AuditOutboxRepository.OutboxRow("audit-2", "{}", 1));
|
||||
doThrow(new IllegalStateException("broker unavailable"))
|
||||
.when(rocketMQ).syncSend(anyString(), any(Message.class), anyLong());
|
||||
|
||||
publisher.publish();
|
||||
|
||||
verify(repository).failed("audit-2", "test-owner", 5, 5, "broker unavailable");
|
||||
}
|
||||
|
||||
private static AuditEvent event(String id) {
|
||||
return new AuditEvent(id, "ROLE_UPDATE", "ROLE", "1", "修改角色",
|
||||
"request-1", "trace-1", 1L, 1L, 1L, "admin", "PLATFORM", "WEB",
|
||||
"PUT", "/roles/1", "127.0.0.1", 10, true, null, null,
|
||||
null, null, Instant.parse("2026-08-05T00:00:00Z"), "iam-service");
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class Config {
|
||||
@Bean
|
||||
ObjectMapper objectMapper() { return new ObjectMapper().findAndRegisterModules(); }
|
||||
|
||||
@Bean
|
||||
AuditProperties properties() {
|
||||
AuditProperties value = new AuditProperties();
|
||||
value.getOutbox().setBatchSize(50);
|
||||
value.getOutbox().setLeaseSeconds(60);
|
||||
value.getOutbox().setMaxAttempts(5);
|
||||
value.getRocketmq().setTopic("test-baiyue-audit-event-v1");
|
||||
return value;
|
||||
}
|
||||
|
||||
@Bean
|
||||
OutboxAuditSink sink(AuditOutboxRepository repository, ObjectMapper json,
|
||||
TransactionOperations transactions) {
|
||||
return new OutboxAuditSink(repository, json, transactions);
|
||||
}
|
||||
|
||||
@Bean
|
||||
AuditOutboxPublisher publisher(AuditOutboxRepository repository, RocketMQTemplate rocketMQ,
|
||||
AuditProperties properties) {
|
||||
return new AuditOutboxPublisher(repository, rocketMQ, properties, "test-owner");
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user