Files
redis-stream-springboot-sta…/src/test/java/com/njcn/middle/stream/template/RedisStreamEnhanceTemplateTest.java

94 lines
4.2 KiB
Java
Raw Normal View History

package com.njcn.middle.stream.template;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.njcn.middle.stream.domain.StreamBaseMessage;
import com.njcn.middle.stream.support.StreamKeyBuilder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.junit.jupiter.api.Test;
import org.mockito.ArgumentCaptor;
import org.springframework.data.redis.connection.stream.MapRecord;
import org.springframework.data.redis.connection.stream.RecordId;
import org.springframework.data.redis.core.StreamOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import java.util.Map;
import static com.njcn.middle.stream.constant.StreamMessageConstant.ENC_GZIP;
import static com.njcn.middle.stream.constant.StreamMessageConstant.ENC_PLAIN;
import static com.njcn.middle.stream.constant.StreamMessageConstant.F_BODY;
import static com.njcn.middle.stream.constant.StreamMessageConstant.F_ENC;
import static com.njcn.middle.stream.constant.StreamMessageConstant.F_KEY;
import static com.njcn.middle.stream.constant.StreamMessageConstant.F_TAG;
import static com.njcn.middle.stream.constant.StreamMessageConstant.F_TS;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
class RedisStreamEnhanceTemplateTest {
@Data
@EqualsAndHashCode(callSuper = true)
static class Foo extends StreamBaseMessage {
private String name;
}
@SuppressWarnings({"unchecked", "rawtypes"})
private MapRecord<String, String, String> captureSend(boolean compress, Foo foo, String topic, StreamKeyBuilder kb) {
StringRedisTemplate redis = mock(StringRedisTemplate.class);
StreamOperations ops = mock(StreamOperations.class);
doReturn(ops).when(redis).opsForStream();
// send() 内 ofMap 返回 MapRecord编译期绑定 add(MapRecord) 重载(非 add(Record)
doReturn(RecordId.of("0-1")).when(ops).add(any(MapRecord.class));
RedisStreamEnhanceTemplate tpl = new RedisStreamEnhanceTemplate(redis, kb);
RecordId id = tpl.send(topic, foo, compress);
assertEquals("0-1", id.getValue(), "返回 XADD 的 RecordId");
ArgumentCaptor<MapRecord> cap = ArgumentCaptor.forClass(MapRecord.class);
verify(ops).add(cap.capture());
return (MapRecord<String, String, String>) cap.getValue();
}
@Test
void sendPlainFillsFiveFields() {
Foo foo = new Foo();
foo.setTag("t1");
foo.setName("hello");
MapRecord<String, String, String> rec = captureSend(false, foo, "MyTopic", new StreamKeyBuilder(false, ""));
assertEquals("MyTopic", rec.getStream(), "关隔离 → 原 topic 作 stream 名");
Map<String, String> v = rec.getValue();
assertEquals(5, v.size(), "固定五字段 key/tag/enc/body/ts");
assertEquals(foo.getKey(), v.get(F_KEY), "key 取自 message");
assertEquals("t1", v.get(F_TAG), "tag 取自 message");
assertEquals(ENC_PLAIN, v.get(F_ENC), "不压缩 enc=plain");
assertTrue(v.get(F_BODY).contains("hello"), "明文 body 含原文");
assertNotNull(v.get(F_TS), "ts 非空");
}
@Test
void sendCompressUsesGzipAndShorterBody() {
Foo foo = new Foo();
foo.setName(StrUtil.repeat("abcdefgh", 200));
String json = JSONObject.toJSONString(foo);
MapRecord<String, String, String> rec = captureSend(true, foo, "MyTopic", new StreamKeyBuilder(false, ""));
Map<String, String> v = rec.getValue();
assertEquals(ENC_GZIP, v.get(F_ENC), "压缩 enc=gzip");
assertTrue(v.get(F_BODY).length() < json.length(), "压缩 body 短于原 json");
}
@Test
void sendUsesEnvIsolatedStreamName() {
MapRecord<String, String, String> rec =
captureSend(false, new Foo(), "MyTopic", new StreamKeyBuilder(true, "prod"));
assertEquals("MyTopic_prod", rec.getStream(), "开隔离 → stream 名带 env 后缀");
}
}