You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 06:55:54