个人技术分享

概述

使用curator framework框架去操作zookeeper时,我们知道因其的方法风格是那种流式的编写风格,所以我们在写单元测试的时候要把链接zookeeper的操作给mock掉,那么着实是不太好写单测。不过好在curator framework有一个专门用于测试的模块,可以让我们在单测运行之前就在本地启动一个zookeeper server实例,以便于让单测可以直接连接本地的zookeeper实例创建curator client,便于做单元测试。

实现

引入依赖

            <dependency>
                <groupId>org.apache.curator</groupId>
                <artifactId>curator-framework</artifactId>
                <version>4.3.0</version>
            </dependency>
            <dependency>
                <groupId>org.apache.curator</groupId>
                <artifactId>curator-test</artifactId>
                <version>4.3.0</version>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>org.apache.zookeeper</groupId>
                <artifactId>zookeeper</artifactId>
                <version>3.4.14</version>
            </dependency>

启动zookeeper

    private static TestingServer zkServer;

    @BeforeClass
    public static void startZkServer() throws Exception {
        zkServer = new TestingServer(true);
        zkServer.start();
    }

创建curator framework client

    private CuratorFramework zkClient;
    
    @BeforeAll
    public CuratorFramework createCuratorClient() {
        zkClient = CuratorFrameworkFactory.builder()
                //本地启动的zookeeper实例端口,跑单测用
                .connectString(zkServer.getConnectString())
                .retryPolicy(new RetryNTimes(5, 1000))
                .connectionTimeoutMs(40 * 1000)
                .sessionTimeoutMs(5 * 1000).build();

        zkClient.start();
    }

单元测试-创建临时节点

    @Test
    public void test_createEphemeral() {
        String path = "/zk/test";
        
        createEphemeral(path);

        List<String> childrens = getChildren("/zk");

        Assert.assertEquals(1, childrens.size());
   }

   private void createEphemeral(String path) {
        try {
            zkClient.create().withMode(CreateMode.EPHEMERAL).forPath(path);
        } catch (NodeExistsException e) {
            logger.warn("ZNode " + path + " already exists.", e);
            throw new IllegalStateException(e.getMessage(), e);
        } catch (Exception e) {
            throw new IllegalStateException(e.getMessage(), e);
        }
    }

    private List<String> getChildren(String path) {
        try {
            return zkClient.getChildren().forPath(path);
        } catch (NoNodeException e) {
            return new ArrayList<>();
        } catch (Exception e) {
            throw new IllegalStateException(e.getMessage(), e);
        }
    }

单测完毕后关闭zookeeper server

@AfterClass
public static void closeZkServer() throws IOException {
    zkServer.close();
}