【问题标题】:NodeJS EventEmitter test with Mocha使用 Mocha 进行 NodeJS EventEmitter 测试
【发布时间】:2018-07-25 09:34:20
【问题描述】:

我在测试ldapjs 客户端搜索操作时遇到问题。它返回一个 EventEmitter,您必须让其监听某些特定事件。我包装了这个操作来承诺它并定义我的逻辑,我想对它进行单元测试。

findUser(username) {
    return new Promise((resolve, reject) => {
        logger.debug('Searching user: ', username);
        this.ldapClient.bind(user.name, .user.password, err => {
            if (err) return reject(err);
            else
                this.ldapClient.search(root, {filter: `(cn=${username})`}, (errSearch, resSearch) => {
                    if (errSearch) return reject(errSearch);
                    const entries = [];
                    resSearch.on('searchEntry', entry => entries.push(entry.object));
                    resSearch.on('searchReference', referral => reject(new Error(`Received search referall: ${referral}`)));
                    resSearch.on('error', err => reject((err));
                    resSearch.on('end', result => {
                        if (result.status === 0 && entries.length === 1) {
                            return resolve({
                                cn: entries[0].cn,
                                objectclass: entries[0].objectclass,
                                password: entries[0].password
                            });
                        } else {
                            return reject(new Error(`Wrong search result: ${result}`));
                        }
                    });
                });
        });
    });
}

我正在使用 mockerySinon 来替换我模块中的 ldapjs 依赖项:

beforeEach(function () {
    searchEM = new EventEmitter();
    sandbox = sinon.createSandbox();
    ldapClientStub = Stubs.getLdapClientStub(sandbox);
    ldapClientStub.bind.yields(null);
    ldapClientStub.search.withArgs('o=ldap', {filter: `(cn=${findParam})`}).yields(null, searchEM);

    mockery.registerMock('ldapjs', Stubs.getLdapStub(ldapClientStub));
    mockery.registerAllowable('../src/client');

    UserClientCls = require('../src/client').default;
    userClient = new UserClientCls(config.get());
});

it('should return user with given username', function (done) {
    setTimeout(() => {
        searchEM.emit('searchEntry', users[1]);
        searchEM.emit('end', {status: 0});
        console.log('emitted');
    }, 500);
    searchEM.on('end', res => console.log(res));

    userClient.findUser(findParam)
        .then(user => {
            user.cn.should.equal(users[1].attributes.cn);
            user.objectclass.should.equal(users[1].attributes.objectclass);
            user.password.should.equal(users[1].attributes.password);
            return done();
        })
        .catch(err => done(err));
});

问题在于findUser 中定义的侦听器永远不会被调用(但函数本身会被调用)。我在测试中定义的监听器(只是为了调试行为)被正确调用了。

我不明白我是否错过了有关 EventEmitters 工作原理的某些内容,或者我是否以错误的方式进行测试。或者也许我写了一段无法测试的糟糕代码。

【问题讨论】:

    标签: node.js unit-testing mocha.js eventemitter


    【解决方案1】:

    我找到了解决问题的方法。我扩展了基础EventEmitter:我添加了逻辑来存储我想要发出的事件,并用发出我的假事件的逻辑覆盖了它的on 方法。

    class TestEventEmitter extends EventEmitter {
        constructor() {
            super();
        }
    
        setFakeEmit(fakeEmit) {
            this.fakeEmit = fakeEmit;
        }
    
        on(eventName, cb) {
            super.on(eventName, cb);
            if (super.eventNames().length === 4)
                this.fakeEmit.forEach(f => this.emit(f.name, f.obj));
        }
    }
    

    所以,在beforeEach 中,我可以存根ldapClientStub.search 使其返回我的TestEventEmitter

    beforeEach(function() {
        searchEM = new TestEventEmitter();
        searchEM.setFakeEmit([{
            name: 'searchEntry',
            obj: { object: users[1].attributes }
        }, {
            name: 'end',
            obj: { status: 0 }
        }]);
    
        ...
    
        ldapClientStub.search.withArgs('o=ldap', { filter: `(&(cn=${findParam})(objectclass=astsUser))` }).yields(null, searchEM);
    })
    

    这个解决方案可能不是很优雅,但它确实有效。如果有人可以发布更好的解决方案,我会很高兴看看。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-14
      • 1970-01-01
      相关资源
      最近更新 更多