elasticsearch2.1.1集成测试中遇到的问题总结

从elasticsearch1.6.2版本开始,项目组就开始进行基于elasticsearch的应用开发,然而对于这些应用的单元测试则相对落后——在搭建的es测试集群上跑测试用例。其实,es本身提供了易于使用地基础的集成测试能力。在开始es功能的集成测试前,建议阅读es测试官方文档
项目使用的版本是2.1.1,下面遇到的问题都是针对此版本的。

1.elasticsearch中的jarHell问题

解决方案是在测试源码目录src/test/java中添加org.elasticsearch.bootstrap.JarHell类,源码如下:

package org.elasticsearch.bootstrap;
import java.net.URL;
public class JarHell {
    private JarHell() {}
    public static void checkJarHell() throws Exception {}
    public static void checkJarHell(URL urls[]) throws Exception {}
    public static void checkVersionFormat(String targetVersion) {}
    public static void checkJavaVersion(String resource, String targetVersion) {}
    public static URL[] parseClassPath() {return new URL[]{};}
}

参考目录:解决es2.1.1中jarHell问题

2.和EasyMock集成问题

进行单元测试时,经常使用mock对象,项目中主要使用的是EasyMock和PowerMock。
如果测试类是继承自ESIntegTestCase进行继承测试时,要注意,如果使用@Before或者@After标识,则参考LuceneTestCase类中关于此的描述

 * For instance-level setup, use {@link Before} and {@link After} annotated
 * methods. If you override either {@link #setUp()} or {@link #tearDown()} in
 * your subclass, make sure you call super.setUp() and
 * super.tearDown(). This is detected and enforced.

3.设置elasticsearch集群实例的shard和replica数

对于shard个数和备份个数的设置,要重载方法。

@Override
protected int numberOfShards() {
return 1;
}

@Override
protected int numberOfReplicas() {
return 0;
}

参考number of shards

4.给出elasticsearch集成测试的小例子

public class Alias {

    private AliasType aliasType;
    private MGIndex current;

    public Alias(AliasType aliasType) {
        this.aliasType = aliasType;
        current = MGIndexFactory.get(aliasType.getPrefix());
    }

    //对于每个shard设置界限值
    public boolean isNeedAdd(Client client) throws ClusterUnhealthException {
        // Check shard doc
        String index = current.getIndexName();
        IndicesStatsResponse stats = client.admin().indices().prepareStats(index).execute().actionGet();
        if (stats.getFailedShards() > 0) {
            throw new ClusterUnhealthException("Get shards stats failed");
        }

        int docThreshold = current.getDocThreshold();

        for (ShardStats st : stats.getShards()) {
            String info = String.format("%s contains %d files which's threshold is %d", index,
                            st.getStats().getDocs().getCount(), docThreshold);
            MGLogger.info(info);

            if (st.getStats().getDocs().getCount() > docThreshold)
                return true;
        }

        return false;
    }
}

其测试函数如下:

public class AliasTest extends ESIntegTestCase{
    Alias alias = null;

    @Before
    public void setUp() throws Exception {
        super.setUp();
        alias = new Alias(AliasType.ATTACHMENT);
    }

    @After
    public void tearDown() throws Exception {
        super.tearDown();
    }

    @Override
    protected int numberOfShards() {
        return 1;
    }

    @Override
    protected int numberOfReplicas() {
        return 0;
    }

    @Test
    public void testIsNeedAdd() throws Exception {
        indexRandom(true, false,
            client().prepareIndex("test", "type1", "1").setSource("field1", "王宁"),
            client().prepareIndex("test", "type1", "2").setSource("field1", "个人电话"),
            client().prepareIndex("test", "type1", "3").setSource("field1", "12")
        );

        refresh();
        MGIndex mgIndexMock = EasyMock.createMock(MGIndex.class);
        EasyMock.expect(mgIndexMock.getIndexName()).andReturn("test").times(2);
        EasyMock.expect(mgIndexMock.getDocThreshold()).andReturn(5).times(2);
        EasyMock.replay(mgIndexMock);
        alias.setCurrent(mgIndexMock);

        assertFalse(alias.isNeedAdd(client()));

        indexRandom(true, false,
            client().prepareIndex("test", "type1", "4").setSource("field1", "王宁"),
            client().prepareIndex("test", "type1", "5").setSource("field1", "个人电话"),
            client().prepareIndex("test", "type1", "6").setSource("field1", "12")
        );

        assertTrue(alias.isNeedAdd(client()));

        EasyMock.verify(mgIndexMock);
    }
}

测试用例AliasTest中,使用EasyMock来mock current对象,通过继承ESIntegTestCase来进行es功能的集成测试——构筑一个只有一个shard无备份的集群,shard中文档的个数大于5时,使得isNeedAdd的返回值为空。

5.PowerMock和ESIntegTestCase配合产生的问题

由于ESIntegTestCase的祖先LuceneTestCase使用@RunWith(RandomizedRunner.class)和PowerMock在mock static函数时,使用的@RunWith(PowerMockRunner.class)冲突,使用这种方法无法将es的集成测试和PowerMock mock static 函数的能力结合在一起,尝试了Bootstrap using a Junit Rule和Delegate to another JUnit Runner仍没解决ESIntegTestCase和PowerMock融合的问题,记录留待解决。

你可能感兴趣的:(elasticsearch2.1.1集成测试中遇到的问题总结)