ClientBuilderTest.java
package redis.clients.jedis.builders;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.containsString;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.Mockito.*;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Collections;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import redis.clients.jedis.CommandObject;
import redis.clients.jedis.JedisPooled;
import redis.clients.jedis.JedisSentineled;
import redis.clients.jedis.args.Rawable;
import redis.clients.jedis.csc.Cache;
import redis.clients.jedis.executors.CommandExecutor;
import redis.clients.jedis.providers.ConnectionProvider;
import redis.clients.jedis.json.JsonObjectMapper;
import redis.clients.jedis.json.Path2;
import redis.clients.jedis.search.FTSearchParams;
@ExtendWith(MockitoExtension.class)
class ClientBuilderTest {
@Mock
CommandExecutor exec;
@Mock
ConnectionProvider provider;
@Captor
ArgumentCaptor<CommandObject<?>> cap;
private static List<String> argsToStrings(CommandObject<?> co) {
List<String> out = new ArrayList<>();
for (Rawable r : co.getArguments()) {
out.add(new String(r.getRaw(), StandardCharsets.UTF_8));
}
return out;
}
@Test
void appliesKeyPreprocessorToCommandObjects() {
try (JedisPooled client = JedisPooled.builder().commandExecutor(exec)
.connectionProvider(provider).keyPreProcessor(k -> "prefix:" + k).build()) {
client.set("key", "v");
}
verify(exec).executeCommand(cap.capture());
assertThat(argsToStrings(cap.getValue()), contains("SET", "prefix:key", "v"));
}
@Test
void appliesJsonObjectMapper() {
JsonObjectMapper mapper = mock(JsonObjectMapper.class);
when(mapper.toJson(any())).thenReturn("JSON:{a=1}");
try (JedisPooled client = JedisPooled.builder().commandExecutor(exec)
.connectionProvider(provider).jsonObjectMapper(mapper).build()) {
client.jsonSetWithEscape("k", Path2.ROOT_PATH, Collections.singletonMap("a", 1));
}
verify(exec).executeCommand(cap.capture());
assertThat(argsToStrings(cap.getValue()), contains("JSON.SET", "k", "$", "JSON:{a=1}"));
}
@Test
void appliesSearchDialect() {
try (JedisPooled client = JedisPooled.builder().commandExecutor(exec)
.connectionProvider(provider).searchDialect(3).build()) {
client.ftSearch("idx", "q", new FTSearchParams());
}
verify(exec, atLeastOnce()).executeCommand(cap.capture());
List<String> args = argsToStrings(cap.getValue());
assertThat(args, contains("FT.SEARCH", "idx", "q", "DIALECT", "3"));
}
@Test
void cacheRequiresRESP3() {
Cache cache = mock(Cache.class);
IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> JedisPooled
.builder().commandExecutor(exec).connectionProvider(provider).cache(cache).build(),
"Cache requires RESP3");
assertThat(ex.getMessage(), containsString("Client-side caching is only supported with RESP3"));
}
@Test
void standaloneValidateHostPortRequired() {
IllegalArgumentException ex = assertThrows(IllegalArgumentException.class,
() -> JedisPooled.builder().hostAndPort(null).build());
assertThat(ex.getMessage(), containsString("Either URI or host/port must be specified"));
}
@Test
void sentinelValidateMasterAndSentinels() {
IllegalArgumentException ex = assertThrows(IllegalArgumentException.class,
() -> JedisSentineled.builder().build());
assertThat(ex.getMessage(), containsString("Master name is required for Sentinel mode"));
ex = assertThrows(IllegalArgumentException.class,
() -> JedisSentineled.builder().masterName("mymaster").build());
assertThat(ex.getMessage(),
containsString("At least one sentinel must be specified for Sentinel mode"));
ex = assertThrows(IllegalArgumentException.class, () -> JedisSentineled.builder()
.masterName("mymaster").sentinels(Collections.emptySet()).build());
assertThat(ex.getMessage(),
containsString("At least one sentinel must be specified for Sentinel mode"));
}
}