You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
120 lines
5.9 KiB
120 lines
5.9 KiB
package com.mydreamjob.messaging;
|
|
|
|
import com.mydreamjob.common.exception.BusinessException;
|
|
import com.mydreamjob.common.exception.ErrorCode;
|
|
import com.mydreamjob.messaging.dto.CreateConversationRequest;
|
|
import com.mydreamjob.messaging.dto.MessagePageResponse;
|
|
import com.mydreamjob.messaging.dto.SendMessageRequest;
|
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
import org.junit.jupiter.api.BeforeEach;
|
|
import org.junit.jupiter.api.Test;
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
|
|
import org.springframework.boot.test.context.SpringBootTest;
|
|
import org.springframework.boot.test.mock.mockito.MockBean;
|
|
import org.springframework.data.redis.core.RedisTemplate;
|
|
import org.springframework.data.redis.core.ValueOperations;
|
|
import org.springframework.http.MediaType;
|
|
import org.springframework.test.context.ActiveProfiles;
|
|
import org.springframework.test.web.servlet.MockMvc;
|
|
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
|
|
import static org.mockito.ArgumentMatchers.any;
|
|
import static org.mockito.ArgumentMatchers.eq;
|
|
import static org.mockito.Mockito.*;
|
|
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
|
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
|
|
|
|
@SpringBootTest
|
|
@AutoConfigureMockMvc
|
|
@ActiveProfiles("integration-test")
|
|
class MessagingControllerTest {
|
|
|
|
@Autowired private MockMvc mockMvc;
|
|
@Autowired private com.mydreamjob.auth.JwtTokenProvider jwtTokenProvider;
|
|
@MockBean private MessagingService messagingService;
|
|
@MockBean private RedisTemplate<String, Object> redisTemplate;
|
|
private final ObjectMapper mapper = new ObjectMapper();
|
|
|
|
@BeforeEach
|
|
@SuppressWarnings("unchecked")
|
|
void setUp() {
|
|
ValueOperations<String, Object> ops = mock(ValueOperations.class);
|
|
when(redisTemplate.opsForValue()).thenReturn(ops);
|
|
when(redisTemplate.hasKey(any())).thenReturn(false);
|
|
}
|
|
|
|
private String token() {
|
|
return "Bearer " + jwtTokenProvider.generateAccessToken(100L, "1", Map.of("roles", "STUDENT"));
|
|
}
|
|
|
|
@Test void listConversations_shouldReturn200() throws Exception {
|
|
when(messagingService.listConversations(100L)).thenReturn(List.of());
|
|
mockMvc.perform(get("/conversations").header("Authorization", token()))
|
|
.andExpect(status().isOk()).andExpect(jsonPath("$.code").value(200));
|
|
}
|
|
|
|
@Test void getConversation_shouldReturn200() throws Exception {
|
|
when(messagingService.getConversation(1L, 100L)).thenReturn(Map.of("id", 1, "type", "DIRECT"));
|
|
mockMvc.perform(get("/conversations/1").header("Authorization", token()))
|
|
.andExpect(status().isOk()).andExpect(jsonPath("$.data.id").value(1));
|
|
}
|
|
|
|
@Test void createConversation_shouldReturn200() throws Exception {
|
|
CreateConversationRequest req = new CreateConversationRequest();
|
|
req.setParticipantUserId(200L);
|
|
when(messagingService.createOrGetDirectConversation(eq(100L), any()))
|
|
.thenReturn(Map.of("id", 2, "type", "DIRECT"));
|
|
mockMvc.perform(post("/conversations").header("Authorization", token())
|
|
.contentType(MediaType.APPLICATION_JSON).content(mapper.writeValueAsString(req)))
|
|
.andExpect(status().isOk()).andExpect(jsonPath("$.data.id").value(2));
|
|
}
|
|
|
|
@Test void sendMessage_shouldReturn200() throws Exception {
|
|
SendMessageRequest req = new SendMessageRequest();
|
|
req.setConversationId(1L); req.setContent("Hello");
|
|
when(messagingService.sendMessage(eq(100L), any())).thenReturn(Map.of("id", 1, "content", "Hello"));
|
|
mockMvc.perform(post("/conversations/messages").header("Authorization", token())
|
|
.contentType(MediaType.APPLICATION_JSON).content(mapper.writeValueAsString(req)))
|
|
.andExpect(status().isOk()).andExpect(jsonPath("$.data.content").value("Hello"));
|
|
}
|
|
|
|
@Test void listMessages_shouldReturn200() throws Exception {
|
|
when(messagingService.listMessages(eq(1L), eq(100L), eq(0), eq(20)))
|
|
.thenReturn(MessagePageResponse.builder().items(List.of()).total(0).page(0).size(20).totalPages(0).build());
|
|
mockMvc.perform(get("/conversations/1/messages").header("Authorization", token()))
|
|
.andExpect(status().isOk()).andExpect(jsonPath("$.code").value(200));
|
|
}
|
|
|
|
@Test void markRead_shouldReturn200() throws Exception {
|
|
doNothing().when(messagingService).markRead(1L, 100L);
|
|
mockMvc.perform(post("/conversations/1/read").header("Authorization", token()))
|
|
.andExpect(status().isOk()).andExpect(jsonPath("$.code").value(200));
|
|
}
|
|
|
|
@Test void createConversation_noToken_shouldReturn401() throws Exception {
|
|
String body = mapper.writeValueAsString(Map.of("participantUserId", 200));
|
|
mockMvc.perform(post("/conversations").contentType(MediaType.APPLICATION_JSON).content(body))
|
|
.andExpect(status().isUnauthorized());
|
|
}
|
|
|
|
// ── 会话不存在 → 404/8305;非成员 → 403/2002 ────────────────
|
|
|
|
@Test void getConversation_notFound_shouldReturn404() throws Exception {
|
|
when(messagingService.getConversation(1L, 100L))
|
|
.thenThrow(new BusinessException(ErrorCode.CONVERSATION_NOT_FOUND));
|
|
mockMvc.perform(get("/conversations/1").header("Authorization", token()))
|
|
.andExpect(status().isNotFound())
|
|
.andExpect(jsonPath("$.code").value(8305));
|
|
}
|
|
|
|
@Test void getConversation_asNonMember_shouldReturn403() throws Exception {
|
|
when(messagingService.getConversation(1L, 100L))
|
|
.thenThrow(new BusinessException(ErrorCode.FORBIDDEN));
|
|
mockMvc.perform(get("/conversations/1").header("Authorization", token()))
|
|
.andExpect(status().isForbidden())
|
|
.andExpect(jsonPath("$.code").value(2002));
|
|
}
|
|
}
|
|
|