测试
测试是开发应用程序最重要的部分之一。该客户端在测试方面非常灵活,并且与大多数测试框架兼容(例如 ava,它被用于下面的示例中)。
如果您正在使用此客户端,您很可能正在使用 Elasticsearch,您面临的首要问题之一是如何测试您的应用程序。一个完全可行的解决方案是使用真实的 Elasticsearch 实例来测试您的应用程序,但这将变成集成测试,而您想要的是单元测试。有很多方法可以解决这个问题,您可以使用 Docker 创建数据库,或者使用内存兼容的数据库,但是如果您编写的是可以轻松并行化的单元测试,这就会变得非常不便。在进行单元测试时,改善测试体验的另一种方法是使用模拟(mock)。
该客户端的设计旨在易于扩展和适应您的需求。得益于其内部架构,它允许您更改某些特定组件,同时保持其余部分正常工作。每个 Elasticsearch 官方客户端都由以下组件组成
API layer:您可以调用的每个 Elasticsearch API。Transport:负责在发送请求之前准备请求以及处理所有重试和嗅探策略的组件。ConnectionPool:Elasticsearch 是一个集群,可能包含多个节点,ConnectionPool负责管理它们。Serializer:一个包含所有序列化策略的类,从基础的 JSON 到换行符分隔的 JSON。Connection:实际的 HTTP 库。
使用官方客户端模拟 Elasticsearch 的最佳方式是替换 Connection 组件,因为它承担的职责非常少,除了接收请求和返回响应之外,不与其他内部组件交互。
每次为测试编写模拟可能会很烦人且容易出错,因此我们专门为该客户端构建了一个简单而强大的模拟库,您可以使用以下命令安装它
npm install @elastic/elasticsearch-mock --save-dev
使用此库,您可以为发送给 Elasticsearch 的任何请求创建自定义模拟。它提供了一个简单直观的 API,并且只模拟 HTTP 层,让客户端的其他部分照常工作。
在展示它的所有功能以及您可以用它做什么之前,让我们先看一个示例
const { Client } = require('@elastic/elasticsearch')
const Mock = require('@elastic/elasticsearch-mock')
const mock = new Mock()
const client = new Client({
cloud: { id: '<cloud-id>' },
auth: { apiKey: 'base64EncodedKey' },
Connection: mock.getConnection()
})
mock.add({
method: 'GET',
path: '/'
}, () => {
return { status: 'ok' }
})
client.info().then(console.log, console.log)
如您所见,它与客户端本身紧密协作,一旦您创建了模拟库的新实例,您只需调用 mock.getConnection() 方法并将结果传递给客户端的 Connection 选项。从现在开始,每个请求都由模拟库处理,HTTP 层将永远不会被触及。因此,您的测试速度会显著加快,并且您可以轻松地并行运行它们!
该库允许您编写“严格”和“宽松”的模拟,这意味着您可以编写一个处理非常特定请求的模拟,或者更宽松地处理一组请求,让我们看看它的实际应用
mock.add({
method: 'POST',
path: '/indexName/_search'
}, () => {
return {
hits: {
total: { value: 1, relation: 'eq' },
hits: [{ _source: { baz: 'faz' } }]
}
}
})
mock.add({
method: 'POST',
path: '/indexName/_search',
body: { query: { match: { foo: 'bar' } } }
}, () => {
return {
hits: {
total: { value: 0, relation: 'eq' },
hits: []
}
}
})
在上面的示例中,每个搜索请求都会得到第一个响应,而任何使用第二个模拟中所描述的查询的搜索请求都会得到第二个响应。
您还可以指定动态路径
mock.add({
method: 'GET',
path: '/:index/_count'
}, () => {
return { count: 42 }
})
client.count({ index: 'foo' }).then(console.log, console.log)
client.count({ index: 'bar' }).then(console.log, console.log)
- => { count: 42 }
- => { count: 42 }
并且还支持通配符。
另一个非常有趣的用例是能够创建一个随机失败的测试,以查看您的代码对失败的反应
mock.add({
method: 'GET',
path: '/:index/_count'
}, () => {
if (Math.random() > 0.8) {
return ResponseError({ body: {}, statusCode: 500 })
} else {
return { count: 42 }
}
})
我们已经看到了模拟 Elasticsearch 和测试您的应用程序是多么简单,您可以在 模块文档 中找到更多功能和示例。