如何与开玩笑嘲笑Elasticsearch?
#node #测试 #elasticsearch #jest

最初出版的here

介绍

我想您可能正在使用Elasticsearch或计划,因为您已经打开了本文ð另一个假设 - 您肯定会发现通过某些集成测试锁定功能是一个好主意。真的是!

当前工作的公司拥有90%以上的代码覆盖范围,并具有集成测试!我建议每个人都通过测试覆盖他们的代码库,因为正如一个智者所说:

[没有单位测试]您不进行重构,您只是更改狗屎。
hamletdâarcy

设置

想象一下,您有一台简单的RESTFUL服务器,其中包含一些使用Elasticsearch的逻辑。在当前的展示柜中。

const Hapi = require('@hapi/hapi');
const Qs = require('qs');
const {createHandler} = require("./create/index.js");
const {readAllHandler, readHandler} = require("./read/index.js");
const {updateHandler} = require("./update/index.js");
const {deleteAllHandler, deleteHandler} = require("./delete/index.js");

const init = async () => {

    const server = Hapi.server({
    port: 3000,
    host: 'localhost',
    query: {
        parser: (query) => Qs.parse(query)
    }
    });

    server.route({
    method: 'POST',
    path: '/',
    handler: createHandler
    });

    server.route({
    method: 'GET',
    path: '/{id}',
    handler: readHandler
    });

    server.route({
    method: 'GET',
    path: '/',
    handler: readAllHandler
    });

    server.route({
    method: 'PATCH',
    path: '/{id}',
    handler: updateHandler
    });

    server.route({
    method: 'DELETE',
    path: '/{id}',
    handler: deleteHandler
    });

    server.route({
    method: 'DELETE',
    path: '/',
    handler: deleteAllHandler
    });

    await server.start();

    server.events.on('log', (event, tags) => {
    console.log({event}, {tags})
    if (tags.error) {
        console.log(`Server error: ${event.error ? event.error.message : 'unknown'}`);
    }
    });
    console.log('Server running on %s', server.info.uri);
};

process.on('unhandledRejection', (err) => {

    console.log(err);
    process.exit(1);
});

init();

现在,您需要使用一些测试来涵盖每条路线的逻辑,以锁定功能并防止商业逻辑被打破。

一个明显但并不简单的解决方案是每次都使用Docker并旋转弹性进行测试。

但是,值得吗?我的意思是您真的想在管道环境中有更长的时间?也许已经有解决方案了?

此插件下载并在开玩笑开始时,请下载和缓存弹性搜索二进制文件,然后插件自动在定义的端口上启动弹性,并在完成测试后将其撕下。

如何添加测试?

我有一个在pull request中设置有/没有开玩笑测试的示例,因此您可以比较所有更改。但是现在让我们逐步通过它。

1.安装其他模块

yarn add --dev jest @shelf/jest-elasticsearch @types/jest

2.添加Jest-config.js

touch jest.config.js
module.exports = {
    preset: '@shelf/jest-elasticsearch',
    clearMocks: true,
    collectCoverage: true,
    coverageDirectory: "coverage",
    coverageProvider: "v8"
};

另外,您可以使用CLI tool自行生成Jest Config。

3.为插件添加jest-es-config.js

touch jest-es-config.js
const {index} = require('./src/elastic.js');

module.exports = () => {
    return {
    esVersion: '8.4.0',
    clusterName: 'things-cluster',
    nodeName: 'things-node',
    port: 9200,
    indexes: [
        {
        name: index,
        body: {
            settings: {
            number_of_shards: '1',
            number_of_replicas: '1'
            },
            mappings: {
            dynamic: false,
            properties: {
                id: {
                type: 'keyword'
                },
                value: {
                type: 'integer'
                },
                type: {
                type: 'keyword'
                },
                name: {
                type: 'keyword'
                },
            }
            }
        }
        }
    ]
    };
};

4.扩展软件包。JSON脚本进行测试

{
    "scripts": {
    "test": "jest"
    "serve": "node src/index.js"
    }
}

5.调整弹性客户端

const dotenv = require('dotenv')
dotenv.config()
const {Client} = require('@elastic/elasticsearch');

module.exports.client = new Client({
    node: process.env.NODE_ENV === 'test' ? 'http://localhost:9200' : process.env.ES_URL
})

module.exports.index = 'things'

添加一个条件,每当我们运行测试时,都会使用node_env连接到本地旋转的弹性。

利润!

现在所有的东西都准备好编写和运行测试。所有路线都在这里完全覆盖并存储:
elastic-jest-example

作为示例,让封面创建功能业务逻辑。

const {ulid} = require('ulid');
const {client, index} = require("../elastic.js");

module.exports.createHandler = async (request, h) => {
    if (Object.keys(request.payload))
    try {
        const res = await this.create(request.payload)
        return h.response(res).code(200);
    } catch (e) {
        console.log({e})
        return h.response({e}).code(400);
    }
}

// let's cover this function with some tests
module.exports.create = async (entity) => {
    const {
    type,
    value,
    name,
    } = entity;

    const document = {
    id: ulid(),
    type: type.trim().toLowerCase(),
    value: +value.toFixed(0),
    name: name.trim()
    }

    await client.index({
    index,
    document
    });
    return document.id
}

创建一个测试文件并添加几个语句。

touch  src/create/index.test.js
const {create} = require("./index.js");
const {client, index} = require("../elastic");

describe('#create', () => {

// clear elastic every time before running it the statement.
// It's really important since each test would be idempotent.
    beforeEach(async () => {
    await client.deleteByQuery({
        index,
        query: {
        match_all: {}
        }
    })
    await client.indices.refresh({index})
    })

    it('should insert data', async () => {
    expect.assertions(3);
    const res = await create({type: 'some', value: 100, name: 'jacket'})
    await client.indices.refresh();
    const data = await client.search({
        index,
        query: {
        match: {
            "id": res
        }
        }
    })

    expect(res).toEqual(expect.any(String))
    expect(res).toHaveLength(26);
    expect(data.hits.hits[0]._source).toEqual({
        "id": res,
        "name": "jacket",
        "type": "some",
        "value": 100
        }
    );
    })

    it('should insert and process the inserted fields', async () => {
    const res = await create({type: 'UPPERCASE', value: 25.99, name: ' spaces '})
    await client.indices.refresh();
    const data = await client.search({
        index,
        query: {
        match: {
            "id": res
        }
        }
    })
    expect(data.hits.hits[0]._source).toEqual({
        "id": res,
        "name": "spaces",
        "type": "uppercase",
        "value": 26
        }
    );
    })
});

可以简单地描述每个业务逻辑功能的基本测试流:

插入数据 - >运行测试的功能 - >检查输出 - >清除数据 - >重复

数据插入/删除可以通过将其统一为助手并使用其他mooching libs来改进。

弹性拆卸由@shelf/jest-elasticsearch lib本身管理。

遵循的另一个好惯例是覆盖您正在使用DorcidentBlock测试的每个功能,因此以后您可以轻松地使用IDE助手进行特定的测试,而无需重新整体套件:

Running jest tests using Webstorm

资源

现在您知道如何使用开玩笑测试弹性搜索查询。
jest-elasticsearch

另外,您有一个小的蓝图存储库,并准备使用设置!
elastic-jest-example

希望本文能够帮助您设置并测试弹性项目!

想连接吗?

Twitter上关注我!

阅读更多:
How to update 63 million records in MongoDB 50% faster?

Optimizing massive MongoDB inserts, load 50 million records faster by 33%!