feat: extend operation log service and repository with pagination support

This commit is contained in:
张翔
2026-03-18 22:34:43 +08:00
parent 157aee2ffc
commit 8a0cd64829
81 changed files with 8842 additions and 509 deletions
@@ -0,0 +1 @@
cn.novalon.manage.notify.config.WebSocketConfig
@@ -0,0 +1,252 @@
package cn.novalon.manage.notify.handler;
import cn.novalon.manage.notify.core.domain.SysNotice;
import cn.novalon.manage.notify.core.service.ISysNoticeService;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.http.HttpStatus;
import org.springframework.mock.web.reactive.function.server.MockServerRequest;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.reactive.function.server.ServerResponse;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.test.StepVerifier;
import java.time.LocalDateTime;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.*;
@ExtendWith(MockitoExtension.class)
class SysNoticeHandlerTest {
@Mock
private ISysNoticeService noticeService;
private SysNoticeHandler noticeHandler;
private SysNotice testNotice;
@BeforeEach
void setUp() {
noticeHandler = new SysNoticeHandler(noticeService);
testNotice = new SysNotice();
testNotice.setId(1L);
testNotice.setNoticeTitle("系统维护通知");
testNotice.setNoticeType("SYSTEM");
testNotice.setNoticeContent("系统将于今晚进行维护");
testNotice.setStatus("PUBLISHED");
testNotice.setCreateBy("admin");
testNotice.setCreatedAt(LocalDateTime.now());
}
@Test
void testGetAllNotices() {
when(noticeService.getAllNotices()).thenReturn(Flux.just(testNotice));
ServerRequest request = MockServerRequest.builder().build();
Mono<ServerResponse> response = noticeHandler.getAllNotices(request);
StepVerifier.create(response)
.expectNextMatches(serverResponse ->
serverResponse.statusCode() == HttpStatus.OK)
.verifyComplete();
verify(noticeService).getAllNotices();
}
@Test
void testGetNoticeById() {
when(noticeService.getNoticeById(1L)).thenReturn(Mono.just(testNotice));
ServerRequest request = MockServerRequest.builder()
.pathVariable("id", "1")
.build();
Mono<ServerResponse> response = noticeHandler.getNoticeById(request);
StepVerifier.create(response)
.expectNextMatches(serverResponse ->
serverResponse.statusCode() == HttpStatus.OK)
.verifyComplete();
verify(noticeService).getNoticeById(1L);
}
@Test
void testGetNoticeById_NotFound() {
when(noticeService.getNoticeById(999L)).thenReturn(Mono.empty());
ServerRequest request = MockServerRequest.builder()
.pathVariable("id", "999")
.build();
Mono<ServerResponse> response = noticeHandler.getNoticeById(request);
StepVerifier.create(response)
.expectNextMatches(serverResponse ->
serverResponse.statusCode() == HttpStatus.NOT_FOUND)
.verifyComplete();
verify(noticeService).getNoticeById(999L);
}
@Test
void testGetNoticesByStatus() {
when(noticeService.getNoticesByStatus("PUBLISHED")).thenReturn(Flux.just(testNotice));
ServerRequest request = MockServerRequest.builder()
.pathVariable("status", "PUBLISHED")
.build();
Mono<ServerResponse> response = noticeHandler.getNoticesByStatus(request);
StepVerifier.create(response)
.expectNextMatches(serverResponse ->
serverResponse.statusCode() == HttpStatus.OK)
.verifyComplete();
verify(noticeService).getNoticesByStatus("PUBLISHED");
}
@Test
void testGetNoticesByStatus_Draft() {
when(noticeService.getNoticesByStatus("DRAFT")).thenReturn(Flux.empty());
ServerRequest request = MockServerRequest.builder()
.pathVariable("status", "DRAFT")
.build();
Mono<ServerResponse> response = noticeHandler.getNoticesByStatus(request);
StepVerifier.create(response)
.expectNextMatches(serverResponse ->
serverResponse.statusCode() == HttpStatus.OK)
.verifyComplete();
verify(noticeService).getNoticesByStatus("DRAFT");
}
@Test
void testCreateNotice() {
SysNotice newNotice = new SysNotice();
newNotice.setNoticeTitle("新通知");
newNotice.setNoticeType("SYSTEM");
newNotice.setNoticeContent("测试内容");
newNotice.setStatus("DRAFT");
when(noticeService.createNotice(any(SysNotice.class))).thenReturn(Mono.just(testNotice));
ServerRequest request = MockServerRequest.builder()
.body(Mono.just(newNotice));
Mono<ServerResponse> response = noticeHandler.createNotice(request);
StepVerifier.create(response)
.expectNextMatches(serverResponse ->
serverResponse.statusCode() == HttpStatus.OK)
.verifyComplete();
verify(noticeService).createNotice(any(SysNotice.class));
}
@Test
void testCreateNotice_WithAllFields() {
SysNotice newNotice = new SysNotice();
newNotice.setNoticeTitle("完整通知");
newNotice.setNoticeType("ANNOUNCEMENT");
newNotice.setNoticeContent("完整内容");
newNotice.setStatus("PUBLISHED");
newNotice.setCreateBy("admin");
when(noticeService.createNotice(any(SysNotice.class))).thenReturn(Mono.just(testNotice));
ServerRequest request = MockServerRequest.builder()
.body(Mono.just(newNotice));
Mono<ServerResponse> response = noticeHandler.createNotice(request);
StepVerifier.create(response)
.expectNextMatches(serverResponse ->
serverResponse.statusCode() == HttpStatus.OK)
.verifyComplete();
verify(noticeService).createNotice(any(SysNotice.class));
}
@Test
void testUpdateNotice() {
SysNotice updateNotice = new SysNotice();
updateNotice.setNoticeTitle("更新后的通知");
updateNotice.setNoticeType("SYSTEM");
updateNotice.setNoticeContent("更新后的内容");
updateNotice.setStatus("PUBLISHED");
when(noticeService.updateNotice(anyLong(), any(SysNotice.class))).thenReturn(Mono.just(testNotice));
ServerRequest request = MockServerRequest.builder()
.pathVariable("id", "1")
.body(Mono.just(updateNotice));
Mono<ServerResponse> response = noticeHandler.updateNotice(request);
StepVerifier.create(response)
.expectNextMatches(serverResponse ->
serverResponse.statusCode() == HttpStatus.OK)
.verifyComplete();
verify(noticeService).updateNotice(1L, updateNotice);
}
@Test
void testUpdateNotice_NotFound() {
SysNotice updateNotice = new SysNotice();
updateNotice.setNoticeTitle("更新后的通知");
when(noticeService.updateNotice(anyLong(), any(SysNotice.class))).thenReturn(Mono.empty());
ServerRequest request = MockServerRequest.builder()
.pathVariable("id", "999")
.body(Mono.just(updateNotice));
Mono<ServerResponse> response = noticeHandler.updateNotice(request);
StepVerifier.create(response)
.expectNextMatches(serverResponse ->
serverResponse.statusCode() == HttpStatus.NOT_FOUND)
.verifyComplete();
verify(noticeService).updateNotice(999L, updateNotice);
}
@Test
void testDeleteNotice() {
when(noticeService.deleteNotice(1L)).thenReturn(Mono.empty());
ServerRequest request = MockServerRequest.builder()
.pathVariable("id", "1")
.build();
Mono<ServerResponse> response = noticeHandler.deleteNotice(request);
StepVerifier.create(response)
.expectNextMatches(serverResponse ->
serverResponse.statusCode() == HttpStatus.OK)
.verifyComplete();
verify(noticeService).deleteNotice(1L);
}
@Test
void testDeleteNotice_NotFound() {
when(noticeService.deleteNotice(999L)).thenReturn(Mono.empty());
ServerRequest request = MockServerRequest.builder()
.pathVariable("id", "999")
.build();
Mono<ServerResponse> response = noticeHandler.deleteNotice(request);
StepVerifier.create(response)
.expectNextMatches(serverResponse ->
serverResponse.statusCode() == HttpStatus.OK)
.verifyComplete();
verify(noticeService).deleteNotice(999L);
}
}
@@ -0,0 +1,181 @@
package cn.novalon.manage.notify.websocket;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.web.reactive.socket.HandshakeInfo;
import org.springframework.web.reactive.socket.WebSocketMessage;
import org.springframework.web.reactive.socket.WebSocketSession;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.test.StepVerifier;
import java.net.URI;
import static org.mockito.Mockito.*;
@ExtendWith(MockitoExtension.class)
class SysWebSocketHandlerTest {
@Mock
private WebSocketSession session;
@Mock
private WebSocketMessage message;
@Mock
private HandshakeInfo handshakeInfo;
private SysWebSocketHandler webSocketHandler;
@BeforeEach
void setUp() {
webSocketHandler = new SysWebSocketHandler();
}
@Test
void testHandle_NewConnection() {
when(session.getHandshakeInfo()).thenReturn(handshakeInfo);
when(handshakeInfo.getUri()).thenReturn(URI.create("ws://localhost/ws?userId=testuser"));
when(session.receive()).thenReturn(Flux.empty());
Mono<Void> result = webSocketHandler.handle(session);
StepVerifier.create(result)
.verifyComplete();
verify(session).receive();
}
@Test
void testHandle_WithUserId() {
when(session.getHandshakeInfo()).thenReturn(handshakeInfo);
when(handshakeInfo.getUri()).thenReturn(URI.create("ws://localhost/ws?userId=123"));
when(session.receive()).thenReturn(Flux.empty());
Mono<Void> result = webSocketHandler.handle(session);
StepVerifier.create(result)
.verifyComplete();
verify(session).receive();
}
@Test
void testHandle_WithoutUserId() {
when(session.getHandshakeInfo()).thenReturn(handshakeInfo);
when(handshakeInfo.getUri()).thenReturn(URI.create("ws://localhost/ws"));
when(session.getId()).thenReturn("test-session-id");
when(session.receive()).thenReturn(Flux.empty());
Mono<Void> result = webSocketHandler.handle(session);
StepVerifier.create(result)
.verifyComplete();
verify(session).receive();
}
@Test
void testHandle_PongMessage() {
when(session.getHandshakeInfo()).thenReturn(handshakeInfo);
when(handshakeInfo.getUri()).thenReturn(URI.create("ws://localhost/ws?userId=testuser"));
when(message.getPayloadAsText()).thenReturn("{\"type\":\"pong\"}");
when(session.receive()).thenReturn(Flux.just(message));
Mono<Void> result = webSocketHandler.handle(session);
StepVerifier.create(result)
.verifyComplete();
verify(session).receive();
verify(message).getPayloadAsText();
}
@Test
void testHandle_SubscribeMessage() {
when(session.getHandshakeInfo()).thenReturn(handshakeInfo);
when(handshakeInfo.getUri()).thenReturn(URI.create("ws://localhost/ws?userId=testuser"));
when(message.getPayloadAsText()).thenReturn("{\"type\":\"subscribe\"}");
when(session.receive()).thenReturn(Flux.just(message));
Mono<Void> result = webSocketHandler.handle(session);
StepVerifier.create(result)
.verifyComplete();
verify(session).receive();
verify(message).getPayloadAsText();
}
@Test
void testHandle_HeartbeatMessage() {
when(session.getHandshakeInfo()).thenReturn(handshakeInfo);
when(handshakeInfo.getUri()).thenReturn(URI.create("ws://localhost/ws?userId=testuser"));
when(message.getPayloadAsText()).thenReturn("{\"type\":\"heartbeat\"}");
when(session.receive()).thenReturn(Flux.just(message));
Mono<Void> result = webSocketHandler.handle(session);
StepVerifier.create(result)
.verifyComplete();
verify(session).receive();
verify(message).getPayloadAsText();
}
@Test
void testHandle_UnknownMessageType() {
when(session.getHandshakeInfo()).thenReturn(handshakeInfo);
when(handshakeInfo.getUri()).thenReturn(URI.create("ws://localhost/ws?userId=testuser"));
when(message.getPayloadAsText()).thenReturn("{\"type\":\"unknown\"}");
when(session.receive()).thenReturn(Flux.just(message));
Mono<Void> result = webSocketHandler.handle(session);
StepVerifier.create(result)
.verifyComplete();
verify(session).receive();
verify(message).getPayloadAsText();
}
@Test
void testHandle_InvalidJson() {
when(session.getHandshakeInfo()).thenReturn(handshakeInfo);
when(handshakeInfo.getUri()).thenReturn(URI.create("ws://localhost/ws?userId=testuser"));
when(message.getPayloadAsText()).thenReturn("invalid json");
when(session.receive()).thenReturn(Flux.just(message));
Mono<Void> result = webSocketHandler.handle(session);
StepVerifier.create(result)
.verifyComplete();
verify(session).receive();
verify(message).getPayloadAsText();
}
@Test
void testHandle_SessionError() {
when(session.getHandshakeInfo()).thenReturn(handshakeInfo);
when(handshakeInfo.getUri()).thenReturn(URI.create("ws://localhost/ws?userId=testuser"));
when(session.receive()).thenReturn(Flux.error(new RuntimeException("Connection error")));
Mono<Void> result = webSocketHandler.handle(session);
StepVerifier.create(result)
.verifyError();
verify(session).receive();
}
@Test
void testSendMessageToUser_SessionNotFound() {
webSocketHandler.sendMessageToUser("nonexistent", java.util.Map.of("type", "notification", "message", "test"));
verify(session, never()).send(any());
}
}