embedded-redis:Redis embedded server for Java integration testing
redis-unit:Redis instance for unit testing applications.
原理:
启动java的嵌入式redis,然后获取启动时的随机端口,通过spring-redis的创建工厂映射自己需要的bean(使用雪球RedisCluster4的,redis-sdk里面有单元测试:git.snowballfinance.com/lib/redis-c…)
RedisCluster4使用步骤:
test-tools项目已经封装了对redis cluster 4的依赖和默认设置,故只需引入pom即可
| ```html com.xueqiu.infra test-tools 1.0.3
| ------------------------------------------------------------------------------------------------------------------------------------------ |
version版本根据实时情况更新
redis cluster 4使用示例:
只需指定你要启动的节点数(示例中启动了三个节点),详情见如下示例地址
示例地址:
源码版:<http://git.snowballfinance.com/lib/test-tools>
| ```html
/** * RedisCluster 4 unit test * * redis 4.X集群的单元测试,同时是为了兼容雪球的redis SDK(RedisCluster至于名字是历史问题向下兼容造成的) */ @Test public void testRedisCluster4(){ TestEnvironment env = new TestEnvironmentBuilder() .withRedisCluster4(3)
``````html
.build(); try { RedisCluster4 redisCluster4 = env.redisCluster4().get(); List<RedisClusterConfig> clusterConfigs = redisCluster4.getRedisClusterConfigList(); System.out.println(clusterConfigs); String connectString = redisCluster4.getConnectionStringList().stream().collect(Collectors.joining(",")); com.xueqiu.infra.redis4.RedisCluster redisClient = RedisClusterImpl.create(connectString, 4, MetricsFactory.create("RedisClusterImplUnitTest")); redisClient.set("k1", "v1"); System.out.println(redisClient.get("k1")); Assert.assertEquals("v1", redisClient.get("k1")); } catch (Exception e) { Assert.assertTrue(false); throw new RuntimeException("redis cluster 4 test error.", e); } }
``` |
| --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
示例地址:
spring版:[http://git.snowballfinance.com/hekuangsheng/xueqiu-push](http://git.snowballfinance.com/lib/xueqiu-push)
| `test的resource目录下添加sql文件` `src` ` ``--main` ` ``--test` ` ``--java` ` ``--包路径` ` ``--TestConfig.java` ` ``--BaseTests.java` ` ``--limit``--RateLimitClientTest.java` |
| --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
BaseTestConfig.java
| ```html
import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.PropertyAccessor; import com.fasterxml.jackson.databind.ObjectMapper; import com.xueqiu.infra.test.tools.TestEnvironment; import com.xueqiu.infra.test.tools.TestEnvironmentBuilder; import com.xueqiu.infra.test.tools.entity.RedisCluster4; import org.springframework.boot.autoconfigure.AutoConfigureOrder; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.ClassPathResource; import org.springframework.data.redis.connection.RedisClusterConfiguration; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.data.redis.core.script.DefaultRedisScript; import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import org.springframework.transaction.PlatformTransactionManager; import javax.sql.DataSource; import java.util.Arrays; import java.util.List; @Configuration @AutoConfigureOrder(0) public class BaseTestConfig { private TestEnvironment env = new TestEnvironmentBuilder() .withH2Database(Arrays.asList("sql/demo_schema.sql", "sql/demo_data.sql")) .withRedisCluster4(4) .build(); @Bean public DataSource dataSource() { return TestEnvironment.jdbcDataSource() .orElseThrow(() -> new RuntimeException("init test data source fail")); } @Bean(name = "xueqiupushTemplate") public JdbcTemplate jdbcTemplate() { return new JdbcTemplate(dataSource()); } @Bean public PlatformTransactionManager transactionManager(DataSource dataSource) { DataSourceTransactionManager tm = new DataSourceTransactionManager(); tm.setDataSource(dataSource); return tm; } @Bean public RedisConnectionFactory factory(){ RedisCluster4 redisCluster4 = TestEnvironment.redisCluster4() .orElseThrow(() -> new RuntimeException("init test redis cluster fail")); List<String> connectionStringList = redisCluster4.getConnectionStringList(); RedisClusterConfiguration redisClusterConfiguration = new RedisClusterConfiguration(connectionStringList); RedisConnectionFactory connectionFactory = new LettuceConnectionFactory(redisClusterConfiguration); return connectionFactory; } @Bean public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory) { StringRedisTemplate template = new StringRedisTemplate(factory); Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); ObjectMapper om = new ObjectMapper(); om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); jackson2JsonRedisSerializer.setObjectMapper(om); template.setValueSerializer(jackson2JsonRedisSerializer); template.afterPropertiesSet(); return template; } @Bean("rateLimitLua") public DefaultRedisScript getRedisScript() { DefaultRedisScript redisScript = new DefaultRedisScript(); redisScript.setLocation(new ClassPathResource("limit/ratelimit.lua")); redisScript.setResultType(java.util.List.class); return redisScript; } @Bean("rateLimitInitLua") public DefaultRedisScript getInitRedisScript() { DefaultRedisScript redisScript = new DefaultRedisScript(); redisScript.setLocation(new ClassPathResource("limit/ratelimitInit.lua")); redisScript.setResultType(Long.class); return redisScript; } }
``` |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
BaseJunit4Test.java
| ```html
import org.junit.Ignore; import org.junit.runner.RunWith; import org.springframework.context.annotation.ComponentScan; import org.springframework.stereotype.Controller; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.TestExecutionListeners; import org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.transaction.TransactionalTestExecutionListener; import org.springframework.transaction.annotation.Transactional; @Ignore @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = BaseTestConfig.class) @TestExecutionListeners(TransactionalTestExecutionListener.class) @Transactional @ComponentScan( basePackages = { "com.xueqiu.infra.push.server.entity", "com.xueqiu.infra.push.server.limit", }, excludeFilters = { @ComponentScan.Filter(Controller.class) } ) public class BaseJunit4Test extends AbstractJUnit4SpringContextTests { }
``` |
| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
RateLimitClientTest.java
| ```html
import com.xueqiu.infra.push.server.BaseJunit4Test; import org.junit.Test; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.data.redis.core.script.RedisScript; import javax.annotation.Resource; import java.util.Collections; import java.util.List; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; public class RateLimitClientTest extends BaseJunit4Test { private static final String UNIT_TEST_KEY = "UNIT_TEST_KEY"; private final static long PERMITS_PER_SECOND = 3250; @Resource private StringRedisTemplate stringRedisTemplate; @Resource(name = "rateLimitLua") private RedisScript<List> rateLimitLua; @Resource(name = "rateLimitInitLua") private RedisScript<Long> rateLimitInitLua; RateLimitClient rateLimitClient = new RateLimitClient(); @Test public void initToken_and_acquireIntervalAndToken_test() { Long acquire = stringRedisTemplate.execute(rateLimitInitLua, Collections.singletonList(rateLimitClient.getKey(UNIT_TEST_KEY)), String.valueOf(PERMITS_PER_SECOND), String.valueOf(PERMITS_PER_SECOND)); assertEquals(Long.valueOf(1L), acquire); boolean result = stringRedisTemplate.hasKey(rateLimitClient.getKey(UNIT_TEST_KEY)); assertTrue(result); List<Object> objectList = stringRedisTemplate.opsForHash().values(rateLimitClient.getKey(UNIT_TEST_KEY)); assertEquals(3, objectList.size()); } }
``` |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |