【问题标题】:How to mock an instance of elasticsearch in Node.js?如何在 Node.js 中模拟 elasticsearch 的实例?
【发布时间】:2017-06-27 09:32:27
【问题描述】:

我正在使用elasticsearch,并想为以下代码编写单元测试:

import * as elasticsearch from "elasticsearch";
import config from "../config";

const client = new elasticsearch.Client({
  host: config.elasticsearch.host,
  log: "trace"
});

export function index(data) {
    return new Promise((resolve, reject) => {
        client.create({
            index: "myindex",
            type: "mytype",
            id: booking.urn,
            body: data
        }).then(resolve, reject);
    });
}

我熟悉 mocha 和 sinon,但是我不知道在这种情况下用于 stub\mock client.create 的好模式。

谁能建议我可以使用的方法?

【问题讨论】:

标签: javascript node.js unit-testing tdd sinon


【解决方案1】:

一种可能的选择是使用proxyquire + sinon 组合

诗乃会伪装Client

const FakeClient = sinon.stub();
FakeClient.prototype.create = sinon.stub().returns("your data");
var fakeClient = new FakeClient();
console.log(fakeClient.create()); // -> "your data"

这样的假客户端可以通过proxyquire注入被测模块:

import proxyquire from 'proxyquire';
const index = proxyquire('./your/index/module', {
  'elasticsearch': { Client: FakeClient }
});

【讨论】:

    【解决方案2】:

    luboskrnac 的答案将在您尝试代理不包含 elasticsearch 客户端的模块时起作用,否则您需要代理嵌套的 elasticsearch 客户端。

    // controller.spec.js
    
    const FakeClient = {};    
    FakeClient.search = () => {};
    sinon.stub(FakeClient, 'search').callsFake((params, cb) => cb(null, {
        hits: {
            hits: [{
                _source: {
                    id: '95254ea9-a0bd-4c26-b5e2-3e9ef819571d',
                },
            }],
        },
    }));
    
    controller = proxyquire('./controller', {
        '../components/es.wrapper': FakeClient,
        '@global': true,
    });
    

    包装器

    // components/es.wrapper.js
    
    const elasticsearch = require('elasticsearch');
    
    const client = new elasticsearch.Client({
        host: process.env.ELASTICSEARCH_HOST,
    });
    
    const wrapper = (method, params, callback) => {
        if (process.env.NODE_ENV === 'development') {
            params.index = `dev_${params.index}`;
        }
        return client[method](params, callback);
    };
    
    // Wrap ES client methods with dev env prefix
    module.exports = {
        search: (params, callback) => {
            return wrapper('search', params, callback);
        },
    }
    

    控制器

    // controller.js
    const es = require('../components/es.wrapper');
    
    module.exports = {
        search: (req, res, next) => {
             ....
             es.search(...)
             ....
        }
    }
    

    【讨论】:

      【解决方案3】:

      我成功使用了 https://www.npmjs.com/package/nock ,模拟了在端口 9200 上对 elasticsearch 主机的调用。

      【讨论】:

      • 您能分享一个工作示例吗?我正在尝试nock("https://xxx-yyy-zzz.us-east-2.es.amazonaws.com:9200").post("/*") 并收到 SSL 错误。不确定最好的调试方式。
      猜你喜欢
      • 1970-01-01
      • 2021-04-26
      • 1970-01-01
      • 2020-06-17
      • 2012-08-30
      • 1970-01-01
      • 1970-01-01
      • 2021-11-19
      相关资源
      最近更新 更多