liyong
10 小时以前 7a23c450f3ac85de7dca1b908de273ff636ce218
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
package cn.iocoder.yudao.module.im.dal.mysql.message;
 
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
import cn.iocoder.yudao.module.im.dal.dataobject.message.ImPrivateMessageDO;
import cn.iocoder.yudao.module.im.enums.message.ImMessageStatusEnum;
import jakarta.annotation.Resource;
import org.junit.jupiter.api.Test;
 
import java.time.LocalDateTime;
import java.util.List;
 
import static org.junit.jupiter.api.Assertions.*;
 
/**
 * {@link ImPrivateMessageMapper} 的单元测试
 *
 * @author 芋道源码
 */
public class ImPrivateMessageMapperTest extends BaseDbUnitTest {
 
    @Resource
    private ImPrivateMessageMapper mapper;
 
    private static final LocalDateTime FAR_PAST = LocalDateTime.of(2000, 1, 1, 0, 0, 0);
 
    // ========== selectListByMinId ==========
 
    @Test
    public void testSelectListByMinId() {
        // 准备:用户 1 发给用户 2
        ImPrivateMessageDO msg1 = buildMessage(1L, 2L, ImMessageStatusEnum.NORMAL);
        mapper.insert(msg1);
        // 用户 2 发给用户 1
        ImPrivateMessageDO msg2 = buildMessage(2L, 1L, ImMessageStatusEnum.NORMAL);
        mapper.insert(msg2);
        // 用户 3 发给用户 4(不相关)
        ImPrivateMessageDO msg3 = buildMessage(3L, 4L, ImMessageStatusEnum.NORMAL);
        mapper.insert(msg3);
 
        // 调用:用户 1 从 id=0 拉取
        List<ImPrivateMessageDO> result = mapper.selectListByMinId(1L, 0L, FAR_PAST, 100);
 
        // 断言:只包含与用户 1 相关的 2 条
        assertEquals(2, result.size());
        assertTrue(result.stream().allMatch(m ->
                m.getSenderId().equals(1L) || m.getReceiverId().equals(1L)));
    }
 
    @Test
    public void testSelectListByMinId_withMinId() {
        // 准备
        ImPrivateMessageDO msg1 = buildMessage(1L, 2L, ImMessageStatusEnum.NORMAL);
        mapper.insert(msg1);
        ImPrivateMessageDO msg2 = buildMessage(2L, 1L, ImMessageStatusEnum.NORMAL);
        mapper.insert(msg2);
 
        // 调用:从 msg1.id 之后拉取
        List<ImPrivateMessageDO> result = mapper.selectListByMinId(1L, msg1.getId(), FAR_PAST, 100);
 
        // 断言:只有 msg2
        assertEquals(1, result.size());
        assertEquals(msg2.getId(), result.get(0).getId());
    }
 
    @Test
    public void testSelectListByMinId_limitSize() {
        // 准备:插入 3 条
        mapper.insert(buildMessage(1L, 2L, ImMessageStatusEnum.NORMAL));
        mapper.insert(buildMessage(2L, 1L, ImMessageStatusEnum.NORMAL));
        mapper.insert(buildMessage(1L, 2L, ImMessageStatusEnum.NORMAL));
 
        // 调用:limit 2
        List<ImPrivateMessageDO> result = mapper.selectListByMinId(1L, 0L, FAR_PAST, 2);
 
        // 断言
        assertEquals(2, result.size());
    }
 
    @Test
    public void testSelectListByMinId_sendTimeFilter() {
        // 准备:一条落在窗口内,一条落在窗口外
        ImPrivateMessageDO newMsg = buildMessage(1L, 2L, ImMessageStatusEnum.NORMAL);
        newMsg.setSendTime(LocalDateTime.now().minusDays(1));
        mapper.insert(newMsg);
        ImPrivateMessageDO oldMsg = buildMessage(1L, 2L, ImMessageStatusEnum.NORMAL);
        oldMsg.setSendTime(LocalDateTime.now().minusDays(40));
        mapper.insert(oldMsg);
 
        // 调用:窗口起点 = 30 天前
        List<ImPrivateMessageDO> result = mapper.selectListByMinId(1L, 0L,
                LocalDateTime.now().minusDays(30), 100);
 
        // 断言:只返回窗口内的消息
        assertEquals(1, result.size());
        assertEquals(newMsg.getId(), result.get(0).getId());
    }
 
    // ========== selectHistoryList ==========
 
    @Test
    public void testSelectHistoryList_basic() {
        // 准备:用户 1 <-> 用户 2 的消息
        ImPrivateMessageDO msg1 = buildMessage(1L, 2L, ImMessageStatusEnum.NORMAL);
        mapper.insert(msg1);
        ImPrivateMessageDO msg2 = buildMessage(2L, 1L, ImMessageStatusEnum.NORMAL);
        mapper.insert(msg2);
        // 用户 1 <-> 用户 3 的消息(不相关)
        ImPrivateMessageDO msg3 = buildMessage(1L, 3L, ImMessageStatusEnum.NORMAL);
        mapper.insert(msg3);
 
        // 调用
        List<ImPrivateMessageDO> result = mapper.selectHistoryList(1L, 2L, null, 100);
 
        // 断言:只有与用户 2 对话的 2 条,按 id 倒序
        assertEquals(2, result.size());
        assertTrue(result.get(0).getId() > result.get(1).getId());
    }
 
    @Test
    public void testSelectHistoryList_includeRecall() {
        // 准备
        ImPrivateMessageDO msg1 = buildMessage(1L, 2L, ImMessageStatusEnum.NORMAL);
        mapper.insert(msg1);
        ImPrivateMessageDO msg2 = buildMessage(1L, 2L, ImMessageStatusEnum.RECALL);
        mapper.insert(msg2);
 
        // 调用
        List<ImPrivateMessageDO> result = mapper.selectHistoryList(1L, 2L, null, 100);
 
        // 断言:撤回消息一并返回
        assertEquals(2, result.size());
        assertEquals(msg2.getId(), result.get(0).getId());
        assertEquals(msg1.getId(), result.get(1).getId());
    }
 
    @Test
    public void testSelectHistoryList_withMaxId() {
        // 准备
        ImPrivateMessageDO msg1 = buildMessage(1L, 2L, ImMessageStatusEnum.NORMAL);
        mapper.insert(msg1);
        ImPrivateMessageDO msg2 = buildMessage(1L, 2L, ImMessageStatusEnum.NORMAL);
        mapper.insert(msg2);
        ImPrivateMessageDO msg3 = buildMessage(1L, 2L, ImMessageStatusEnum.NORMAL);
        mapper.insert(msg3);
 
        // 调用:从 msg3 往前拉
        List<ImPrivateMessageDO> result = mapper.selectHistoryList(1L, 2L, msg3.getId(), 100);
 
        // 断言:只有 msg1 和 msg2
        assertEquals(2, result.size());
        assertTrue(result.stream().allMatch(m -> m.getId() < msg3.getId()));
    }
 
    @Test
    public void testSelectHistoryList_limit() {
        // 准备
        mapper.insert(buildMessage(1L, 2L, ImMessageStatusEnum.NORMAL));
        mapper.insert(buildMessage(2L, 1L, ImMessageStatusEnum.NORMAL));
        mapper.insert(buildMessage(1L, 2L, ImMessageStatusEnum.NORMAL));
 
        // 调用:limit 2
        List<ImPrivateMessageDO> result = mapper.selectHistoryList(1L, 2L, null, 2);
 
        // 断言
        assertEquals(2, result.size());
    }
 
    @Test
    public void testSelectHistoryList_bidirectional() {
        // 准备:验证双向查询
        ImPrivateMessageDO msg1 = buildMessage(2L, 1L, ImMessageStatusEnum.NORMAL); // 对方发的
        mapper.insert(msg1);
 
        // 调用:以用户 1 的视角查
        List<ImPrivateMessageDO> result = mapper.selectHistoryList(1L, 2L, null, 100);
 
        // 断言:能查到对方发来的消息
        assertEquals(1, result.size());
        assertEquals(2L, result.get(0).getSenderId());
    }
 
    // ========== 工具方法 ==========
 
    private ImPrivateMessageDO buildMessage(Long senderId, Long receiverId, ImMessageStatusEnum status) {
        return ImPrivateMessageDO.builder()
                .clientMessageId("uuid-" + System.nanoTime())
                .senderId(senderId)
                .receiverId(receiverId)
                .type(0)
                .content("{\"content\":\"test\"}")
                .status(status.getStatus())
                .sendTime(LocalDateTime.now())
                .build();
    }
 
}