【问题标题】:How to mock req.session on Mocha/Chai API Unit Test如何在 Mocha/Chai API 单元测试中模拟 req.session
【发布时间】:2019-09-09 06:37:07
【问题描述】:

使用 Mocha/Chai 进行 REST API 单元测试,我需要能够为一些端点模拟 req.session.someKey。我该如何去嘲笑req.session

我正在为使用 express-session 的 NodeJS Express 应用程序编写 REST API 单元测试。其中一些端点需要使用存储在req.session.someKey 中的数据,如果req.session.someKey 未定义,则端点设置为返回400,因此我需要能够模拟它才能成功完成测试。

示例代码:

router.get('/api/fileSystems', utilities.apiAuth, (req, res) => {
  let customer = req.session.customer;
  let route = (customer === 'NONE') ? undefined : customer;

  if(route == undefined){
    res.status(400).send('Can't have customer of undefined');
  } else {
    let requestOptions = setRequestOptions(route);
    queryFileSystemInfo(requestOptions, (info) => {
      res.status(200).send(info);
    });

  }
});

我尝试过的:

describe('/GET /api/fileSystems', () => {
  it('It should return information about the filesystem for a customer'), (done) => {
    chai.request(server)
      .get('api/fileSystems')
      .set('customer', '146')
      .end((err, res) => {
        res.should.have.status(200);
        done();
      });
  });
});

我尝试使用 .set() 来设置 req.session 但我相信 .set 只是设置标题,所以我不相信我可以这样更新它,除非我遗漏了什么。

【问题讨论】:

  • 为什么要使用 chai.request?只是模拟控制器

标签: node.js express mocha.js chai chai-http


【解决方案1】:

mock-session 非常适合用来模拟你的会话对象

 let mockSession = require('mock-session');

 describe('/GET /api/fileSystems', () => {
  it('It should return information about the filesystem for a customer'), (done) => {
    let cookie = mockSession('my-session', 'my-secret', {"count":1});  // my-secret is you session secret key. 

    chai.request(server)
      .get('api/fileSystems')
      .set('cookie',[cookie])
      .end((err, res) => {
        res.should.have.status(200);
        done();
      });
  });
});

【讨论】:

  • 感谢您的回复。我已经尝试了 mock-session 包,它看起来像是用于使用 cookies-session 包的应用程序,我不使用它。我使用 express-sessions 包。如果我以这种方式使用模拟会话传入 cookie,它会将 cookie 添加到请求的标头和 cookie 中,但不会更新会话。
【解决方案2】:

对于这个项目,我最终不得不在我们的 server.js 文件中设置 req.session.customer,该文件有一个使用中间件函数设置当前会话的 app.use() 调用。我实际上无法找到在测试时直接改变 req.session 对象的包。

【讨论】:

    【解决方案3】:

    在您的快速设置中,您通常会像这样插入会话中间件

    app.use(session(config))
    

    相反,您可以将会话中间件放在方便访问的位置,并为其制作一个包装器,如下所示:

    app.set('sessionMiddleware') = session(config)
    app.use((...args) => app.get('sessionMiddleware')(...args)
    

    测试需要访问 express 实例,您可以通过重构 /app.js 来导出函数来做到这一点。

    function app () {
      const app = express()
      // ... set up express
      return app
    }
    
    // run app if module called from cli like `node app.js`
    if (require.main === module) instance = app()
    
    module.exports = app
    

    然后在你的测试中,你可以覆盖 app.sessionMiddleware

    describe('/GET /api/fileSystems', () => {
      it('It should return information about the filesystem for a customer'), (done) => {
        app.set('sessionMiddleware') = (req, res, next) => {
          req.session = mockSession // whatever you want here
          next()
        }
        chai.request(server)
          .get('api/fileSystems')
          .set('customer', '146')
          .end((err, res) => {
            res.should.have.status(200);
            done();
          });
    
        // then you can easily run assertions against your mock
        chai.assert.equal(mockSession.value, value)
      });
    });
    

    我在网上看到的其他选项涉及设置一个 cookie 以匹配存储在数据库中的会话,这种方法的问题是当数据库中的会话过期时你最终会遇到问题,所以随着固定装置变得陈旧,测试会随着时间的推移而失败。使用上述方法,您可以通过在测试中设置过期时间来解决此问题。

    【讨论】:

    • 不幸的是appserver 不是同一个东西,所以一旦app.listen 被调用,你就不能覆盖server.sessionMiddleware 上的中间件。我看到的唯一方法是在调用 app.listen 之前注入模拟的中间件。
    • @sassman 抱歉,我在示例测试中将 app 错误命名为 server,我已对其进行了更新。如果/app.js 导出一个返回app 的函数,则测试可以访问实例并更新app.sessionMiddleware
    猜你喜欢
    • 2023-04-11
    • 1970-01-01
    • 2017-03-27
    • 1970-01-01
    • 2018-11-05
    • 2016-09-20
    • 2020-05-30
    • 2018-03-22
    • 2015-06-02
    相关资源
    最近更新 更多