首页 > 解决方案 > 使用 IntelliJ 和 Gradle 调试 Elasticsearch 插件集成测试

问题描述

我正在基于这个示例构建一个 Elasticsearch 插件。该插件使用 Gradle 进行构建、测试、集成测试等。我想使用 IntelliJ 在 Elasticsearch 集成测试中设置断点并对其进行调试。我不在乎我是从 IntelliJ 内部还是在 IntelliJ 外部运行 Gradle 构建,但现在在这两种情况下我都遇到了问题。我将描述我的设置和以下问题:

首先,我通过 CLI 下载并构建/测试示例项目:

$ pip install cookiecutter
$ cookiecutter gh:spinscale/cookiecutter-elasticsearch-ingest-processor
$ # keep all default settings when prompted...
$ gradle build # (also runs the test and integTest tasks)

这运行良好,测试通过。我使用 Gradle ( $ gradle idea) 生成 IntelliJ 项目并在 IntelliJ 中打开它(在目录中显示绿色 Gradle 图标)。我使用默认的 gradle-wrapper 选项并在打开时保留所有其他默认值。

第一个问题:我打开 IntelliJ 的 Gradle 窗口(视图 > 工具窗口 > Gradle),但我没有看到我知道项目中定义的任何 Gradle 任务。这似乎不是什么大不了的事,但拥有它们会很好。


现在我想在 IntelliJ 中运行测试,所以我在org.elasticsearch.plugin.ingest.awesome.AwesomeProcessorTests. 该类扩展了ESTestCaseElasticsearch 的类,但不直接测试任何 Elasticsearch API 交互。

第二个问题:我使用类名旁边的绿色小三角形运行这个测试类。这失败并出现错误java.lang.RuntimeException: unable to install test security manager

我发现我可以通过编辑运行配置并添加 VM 参数来解决这个问题-Dtests.security.manager=false。现在简单的测试运行并通过,我还可以设置断点和调试它们。


现在我想直接测试一些 Elasticsearch 功能,所以我写了一个新的集成测试类来扩展类ESIntegTestCase。测试应该命中 Elasticsearch_cat/plugins端点并检查响应字符串是否为非空。

public class SimpleIT extends ESIntegTestCase {
    private RestClient restClient;
    @Before
    public void setUp() throws Exception {
        super.setUp();
        this.restClient = getRestClient();
    }
    @Override
    protected Collection<Class<? extends Plugin>> nodePlugins() {
        return Collections.singletonList(IngestAwesomePlugin.class);
    }
    public void testPluginInstallation() throws IOException {
        Response response = restClient.performRequest("GET", "_cat/plugins");
        String body = EntityUtils.toString(response.getEntity());
        assertTrue(body.length() > 0);
    }
}

当我通过 CLI ( gradle integTest) 运行它时,测试通过了。如果我添加了一个故意失败的断言(例如assertTrue(body.length() < 0),那么测试就会失败。所以这似乎有效。

第三个问题:当我在 IntelliJ(小绿色三角形)中运行相同的测试时,我收到错误:

java.lang.IllegalArgumentException: no hosts provided

    at __randomizedtesting.SeedInfo.seed([6F620686489164F5:270C27B7060A2BA1]:0)
    at org.elasticsearch.client.RestClientBuilder.<init>(RestClientBuilder.java:68)
    at org.elasticsearch.client.RestClient.builder(RestClient.java:124)
    at org.elasticsearch.test.ESIntegTestCase.createRestClient(ESIntegTestCase.java:2261)
    at org.elasticsearch.test.ESIntegTestCase.createRestClient(ESIntegTestCase.java:2248)
    at org.elasticsearch.test.ESIntegTestCase.createRestClient(ESIntegTestCase.java:2242)
    at org.elasticsearch.test.ESIntegTestCase.getRestClient(ESIntegTestCase.java:2236)
    at org.elasticsearch.plugin.ingest.awesome.SimpleIT.setUp(SimpleIT.java:36)

这映射到我调用的行getRestClient(),这意味着 IntelliJ 正在阻止 Gradle/Elasticsearch 集成测试设置,否则该设置可以在 CLI 中运行。

FWIW,我仍然可以在这一行设置断点并在 IntelliJ 中调试测试类,它将停在该行。


现在我尝试通过 CLI 运行集成测试,在 IntelliJ 中设置断点,并使用 IntelliJ 的远程调试器附加到测试。

我设置了一个新的“远程”运行配置,保持默认设置(传输套接字、调试器模式附加、主机localhost、端口 5005)。在“使用模块的类路径搜索源”选项中,我尝试了所有可能的设置。

我在线上设置了一个断点getRestClient(),并通过 CLI 使用远程调试选项运行 Gradle:

$ GRADLE_OPTS="-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=*:5005" gradle integTest

第四个问题:正如所料,Gradle 进程挂起,显示Listening for transport dt_socket at address: 5005. 我在 IntelliJ 中启动了新的远程任务,然后 Gradle 进程继续运行。不幸的是,它一直运行并且不会在断点处停止。测试仍然通过。


我在网上广泛搜索了附加到 Gradle 调试器的不同方法。我见过很多关于禁用守护进程的事情,我也尝试过使用--system-prop它来传递调试参数,但到目前为止还没有解决这个问题。

标签: javaelasticsearchgradleintellij-ideaintegration-testing

解决方案


推荐阅读