【问题标题】:Why do my Elasticsearch integration tests only work sometimes为什么我的 Elasticsearch 集成测试有时只能工作
【发布时间】:2016-09-06 18:59:10
【问题描述】:

我有以下集成测试:

public class TestElasticIT extends ESIntegTestCase {
  private static final String esIndex = "test";
  private static final String esEntityType = "entity";
  private static final String esDetailType = "details";
  private Client client = null;

  @Before
  public void beforeTests() throws Exception {
     XContentBuilder xContentBuilder = XContentFactory.jsonBuilder().startObject().startObject(esEntityType).endObject().endObject();
     XContentBuilder xContentBuilder2 = XContentFactory.jsonBuilder().startObject().startObject(esDetailType).startObject("_parent").field("type", esEntityType).endObject().endObject().endObject();

     client = ESIntegTestCase.client();
     createIndex(esIndex);

     client.admin().indices().preparePutMapping(esIndex).setType(esDetailType).setSource(xContentBuilder2).get();
     client.admin().indices().preparePutMapping(esIndex).setType(esEntityType).setSource(xContentBuilder).get();
  }

  @Test
  public void testCreateAndRead() throws Exception {
     ensureGreen(esIndex);

     IndexResponse entityResponse = client.prepareIndex(esIndex, esEntityType).setSource(testJson).get(); //This could be any key/value json
     IndexResponse detailResponse = client.prepareIndex(esIndex, esDetailType).setSource(testJsonDetail).setParent(entityResponse.getId()).get();

     //I want to see both parent and child here
     System.out.println(client.prepareSearch().execute().actionGet());
  }  
}

我遇到的问题是client.prepareSearch().execute().actionGet() 只会偶尔返回我的testJson。有时它会起作用,但大多数时候它什么也没返回。如何让我的集成测试每次都能通过?

编辑: 有时有效和无效的查询:

client.prepareGet().setIndex(esIndex).setId(detailResponse.getId()).get();
client.prepareGet().setIndex(esIndex).setType(esDetailType).setRouting(esEntityType).setId(detailResponse.getId()).get();

【问题讨论】:

  • 新条目被解析和索引时会有延迟。我认为您的查询在该过程完成之前正在运行。
  • 如果手动查询索引,数据会显示出来吗?
  • 我不确定您要搜索什么。您应该提供搜索参数以便搜索。如果你想检查你的索引是否成功,你可以使用 isCreated 方法。如果要对数据库执行搜索操作,请提供要搜索的请求参数。
  • 所以我看到的是 isCreated 方法将返回 true。即使我在 println 上设置一个断点并手动执行搜索,它也不会返回我的 json。
  • 我认为这可能与 ES 提供的随机测试有关。或者我没有正确设置客户端。

标签: java elasticsearch junit integration-testing


【解决方案1】:

这是一种竞争条件,可能是因为您没有在创建索引后调用 refresh(),而是依赖 ES 在运行搜索请求之前进行更新。

由于您的课程扩展了 ESIntegTestCase,您应该能够执行类似的操作

this.refresh(esIndex);

有关测试 API 中此方法的更多信息,请参阅以下链接: https://www.elastic.co/guide/en/elasticsearch/reference/current/integration-tests.html https://github.com/elastic/elasticsearch/blob/master/test/framework/src/main/java/org/elasticsearch/test/ESIntegTestCase.java#L1186

这在主要(非测试)Java API 中也可用,如下所示:

client.admin().indices().prepareRefresh(esIndex).get();

有关 Java API 可用性的更多信息,请参见此处: https://static.javadoc.io/org.elasticsearch/elasticsearch/2.3.0/org/elasticsearch/client/IndicesAdminClient.html#refresh(org.elasticsearch.action.admin.indices.refresh.RefreshRequest)

编辑:

我上面提供的第一个 sn-p 仅适用于 Elasticsearch 5.0 Alpha。在当前版本中,刷新方法不带参数: https://github.com/elastic/elasticsearch/blob/v2.4.0/core/src/test/java/org/elasticsearch/test/ESIntegTestCase.java

【讨论】:

  • Refresh 似乎不需要索引。难道我做错了什么?我调用 refresh();在 createIndex(esIndex) 之后,但我仍然看到相同的行为。非常感谢!
  • 调用我提供的第二个代码 sn-p 会发生什么?回头看 github,看来我提供的第一个 sn-p 只适用于 5.0 alpha。
  • 我验证了第一个代码 sn-p 确实只适用于当前的 alpha。我已经更新了我的答案以澄清。当您的意思是“相同的行为”时,即使在刷新调用之后(并且在尝试我发布的第二个 sn-p 之后)它有时仍然有效?
  • 是的,它仍然只是有时有效。我把 refresh() 和 client.admin().indices().prepareRefresh(esIndex).get() 都放在了所有地方,但有时仍然找不到孩子。父母总是在那里。
  • 澄清如果我搜索 esEntityType json,它总是能找到它,但有时它无法找到 esDetailType json。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多