zookeeper单元测试

236 阅读2分钟

curator-test:Contains the TestingServer, the TestingCluster and a few other tools useful for testing.

深坑:

curator竟然不是向下兼容的,issues.apache.org/jira/browse…(使用版本)

log4j-over-slf4j竟然也不是向下兼容的,扯犊子呢,而且外文文档也是一通瞎扯

[惊恐]
[惊恐]
[惊恐]

原理:

启动java的嵌入式zookeeper,然后获取启动时的随机端口,还是使用CuratorFramework封装好的框架进行测试,本来使用的嵌入式curator-test就是它提供的

 


zookeeper使用步骤:

test-tools项目已经封装了对zookeeper的依赖和默认设置,故只需引入pom即可

| ```html com.xueqiu.infra test-tools 1.0.3

| ------------------------------------------------------------------------------------------------------------------------------------------ |

version版本根据实时情况更新

zookeeper使用示例:

只需指定你要启动的节点数(示例中启动了三个节点),详情见如下示例地址

示例地址:

源码版:<http://git.snowballfinance.com/lib/test-tools>

| ```html
/**  * zookeeper unit test  *  * zookeeper的单元测试  */ @Test public void testZookeeper(){     TestEnvironment env = new TestEnvironmentBuilder()             .withZookeeper(3)             .build();  // zookeeper test  try{         TestingCluster cluster = env.zookeepers().get();  String connectString = cluster.getServers().stream().map(server->server.getInstanceSpec().getConnectString()).collect(Collectors.joining(","));  CuratorFramework client = CuratorFrameworkFactory.newClient(connectString, new ExponentialBackoffRetry(1000, 3));  client.start();   client.getConnectionStateListenable().addListener((cl, newState)-> {             System.out.println("连接状态:" + newState.name());  });   List<String> paths = client.getChildren().forPath("/");  System.out.println(paths);  client.create().forPath("/test");   paths = client.getChildren().forPath("/");  System.out.println(paths);   CloseableUtils.closeQuietly(client);  Assert.assertTrue(paths.contains("test"));  }catch (Exception e){         Assert.assertTrue(false);  throw new RuntimeException("zookeeper 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` `          ``--ZookeeperServerTest.java` |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |

TestConfig.java

| ```html
package com.xueqiu.infra.push.server;  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.apache.curator.framework.CuratorFramework; import org.apache.curator.framework.CuratorFrameworkFactory; import org.apache.curator.retry.ExponentialBackoffRetry; import org.apache.curator.test.TestingCluster; 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; import java.util.stream.Collectors;  @Configuration @AutoConfigureOrder(0) public class BaseTestConfig {      private TestEnvironment env = new TestEnvironmentBuilder()             .withZookeeper(3)             .withH2Database(Arrays.asList("sql/demo_schema.sql", "sql/demo_data.sql"))             .withRedisCluster4(4)             .build();      @Bean     public CuratorFramework curatorFramework(){         TestingCluster cluster = TestEnvironment.zookeepers().                 orElseThrow(() -> new RuntimeException("init test TestingServer fail"));         String connectString = cluster.getServers().stream().map(server->server.getInstanceSpec().getConnectString()).collect(Collectors.joining(","));         return CuratorFrameworkFactory.newClient(connectString, new ExponentialBackoffRetry(1000, 3));     }      @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
package com.xueqiu.infra.push.server;  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 {  }
``` |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

ZookeeperServerTest.java

| ```html
package com.xueqiu.infra.push.server;  import org.apache.curator.framework.CuratorFramework; import org.apache.curator.utils.CloseableUtils; import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired;  import java.util.List;  public class ZookeeperServerTest extends BaseJunit4Test {      @Autowired     CuratorFramework curatorFramework;      @Before     public void before(){         curatorFramework.start();     }      @Test     public void zookeeper_server_test() throws Exception {         List<String> paths = curatorFramework.getChildren().forPath("/");         System.out.println(paths);         curatorFramework.create().forPath("/test");          paths = curatorFramework.getChildren().forPath("/");         System.out.println(paths);          Assert.assertTrue(paths.contains("test"));     }      @After     public void after(){         CloseableUtils.closeQuietly(curatorFramework);     } }
``` |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

 

相关资料:

<https://github.com/apache/zookeeper/search?q=HierarchyDynamicMBean&unscoped_q=HierarchyDynamicMBean>

<https://issues.apache.org/jira/browse/CURATOR-428>

<http://curator.apache.org/zk-compatibility.html>

<https://mvnrepository.com/artifact/org.apache.curator/curator-test>

<https://stackoverflow.com/questions/59539375/zookeeper-unit-test-quorumpeer-never-got-set>