如何用Sinon模拟事件?离线测试LDAP客户端数据获取逻辑
模拟LDAP Client的Search事件进行无网络测试
要在无网络环境下测试你的MY_CLASS.getData方法,核心是用Sinon模拟ldapClient.search的回调,并手动触发result对象上的各类事件。下面是分步实现方案:
1. 修正原代码的小问题(重要)
首先,你的原getData方法里,searchEntry事件中return entry是无效的——因为这是异步回调,返回值无法传递到外层的cb。你需要先收集到用户数据,再在end事件里返回:
var MY_CLASS = { getData: function (userId, cb) { if (!ldapConfig) { return cb(new Error('ldap is not configured')); } let userEntry = null; // 新增变量存储用户数据 ldapClient.search('xxxx.com', { // 这里应该是LDAP搜索选项,比如filter: `(uid=${userId})`,原代码的ldapConfig可能有误 }, function (err, result) { if (err) { return cb(err); } result.on('searchEntry', function (entry) { if (entry) { userEntry = entry; // 保存获取到的用户条目 } }); result.on('error', function (err) { cb(err); }); result.on('end', function () { cb(null, userEntry); // 在end事件返回收集到的用户数据 }); }); } };
2. 用Sinon模拟LDAP Search流程
我们需要创建一个模拟的result对象,监听它的on方法,然后手动触发各类事件来模拟真实的LDAP响应:
测试前置准备
const sinon = require('sinon'); const MY_CLASS = require('./your-module-path'); const ldap = require('ldapjs'); // 建议把ldapClient挂载到MY_CLASS上方便测试,比如原代码中添加:MY_CLASS.ldapClient = ldap.createClient(ldapConfig); let mockLdapResult; before(() => { // 创建模拟的result对象,用spy监听on方法,记录所有事件绑定 mockLdapResult = { on: sinon.spy() }; // Stub ldapClient.search方法,调用回调时传入无错误状态和模拟的result sinon.stub(MY_CLASS.ldapClient, 'search').yields(null, mockLdapResult); }); after(() => { // 恢复原方法,避免影响其他测试 MY_CLASS.ldapClient.search.restore(); });
正常场景测试(获取用户数据)
it('should retrieve user data via LDAP search', (done) => { // 定义模拟的LDAP用户条目数据 const mockUserEntry = { dn: 'cn=John Doe,dc=xxxx,dc=com', attributes: [ { type: 'uid', values: ['johndoe'] }, { type: 'cn', values: ['John Doe'] }, { type: 'mail', values: ['john.doe@xxxx.com'] } ] }; // 调用getData方法 MY_CLASS.getData('johndoe', (err, userData) => { // 断言结果 sinon.assert.match(err, null); sinon.assert.match(userData, mockUserEntry); done(); // 标记异步测试完成 }); // 从mockResult的on调用记录中,获取searchEntry事件的回调函数 const searchEntryCallback = mockLdapResult.on.getCall(0).args[1]; // 手动触发searchEntry事件,传入模拟的用户条目 searchEntryCallback(mockUserEntry); // 获取end事件的回调函数并触发,完成LDAP搜索流程 const endCallback = mockLdapResult.on.getCall(2).args[1]; endCallback(); });
错误场景测试(搜索失败)
it('should pass error to callback when LDAP search fails', (done) => { const mockSearchError = new Error('LDAP server unavailable'); // 临时替换stub,让search返回错误 sinon.stub(MY_CLASS.ldapClient, 'search').yields(mockSearchError, null); MY_CLASS.getData('johndoe', (err, userData) => { sinon.assert.match(err, mockSearchError); sinon.assert.match(userData, undefined); done(); }); // 恢复stub MY_CLASS.ldapClient.search.restore(); });
关键思路解释
- 模拟
result对象:通过sinon.spy()监听on方法,我们可以捕获到代码中绑定的所有事件回调。 - 手动触发事件:拿到事件回调后,主动调用它们并传入模拟数据,模拟真实LDAP服务器的响应流程。
- 异步测试处理:因为LDAP操作是异步的,测试时要用
done()函数标记测试完成,确保断言在回调触发后执行。
内容的提问来源于stack exchange,提问作者John Glabb
相关产品推荐
相关产品推荐

