【问题标题】:Stub environment variables using Sinon in Mocha unit tests for Express routes在 Express 路由的 Mocha 单元测试中使用 Sinon 存根环境变量
【发布时间】:2021-10-30 12:47:53
【问题描述】:

我正在努力做到这一点,因此当在我的 TypeScript API 中调用测试路由时,任何需要环境变量的代码都会被抽象出来,因此我们不会连接到任何真实的服务器等。

我的初始快递代码是

router.post("/hello", async (
  req: express.Request,
  res: express.Response,
  next: express.NextFunction
) => {
  const value = await getAValue(req.body)
  ...
}

getAValue() 函数使用环境变量,所以我正在使用 Supertest 为这条路线编写测试

  import request from "supertest";
  import App, { getAValue } from "./src";

  describe("POST /hello", () => {
    it("Returns 200 on expected input", (done) => {
      const payload = {
        "foo":"bar"
      }

      request(App)
        .post("/api/hello")
        .send(payload)
        .expect(200)
        .end((err) => {
          if (err) {
            done(err)
          } else {
            done();
          }
        });
     });
  });

我正在使用存根文件 test/stubs.ts 存根任何需要的函数

import sinon from "sinon"
import { getAValue } from "../src"

sinon.stub(getAValue);

并在我的package.json 中使用我的test 脚本来查找这些存根

"test": "mocha -r ts-node/register -r test/stubs.ts --config=test/.mocharc.json 'test/**/*.ts' --exit"

所以在getAValue() 函数中有一个

import * as env from "env-var";

const value = env.get("VAR_NAME").required().asString();

但我不知何故无法模拟与此相关的任何内容,并且总是得到相同的错误 ERROR: EnvVarError: env-var: "VAR_NAME" is a required variable, but it was not set

我尝试过模拟该函数,或者特别是对 process.env 的调用,但都不起作用。

为 Express 路由测试模拟环境变量的正确方法是什么?

【问题讨论】:

    标签: node.js express unit-testing mocha.js sinon


    【解决方案1】:

    在您的情况下,我有 2 个选择:a) 存根 getAValue() 和 b) 存根 env.get()。您可以根据自己的情况进行选择。

    我使用您的代码并为这个完整的示例对其进行了一些修改:

    // 1. File: src/index.ts
    import express from 'express';
    import * as util from './util';
    
    const app = express();
    
    app.use(express.json());
    
    app.post('/hello', async (
      req: express.Request,
      res: express.Response,
      next: express.NextFunction
    ) => {
      // Need to know whether this function get called.
      console.log('/hello called');
      // Note: Do not use destructure object to call getAValue().
      const value = util.getAValue(req.body);
      // Check for return value.
      console.log('getAValue return:', value);
      // Simplify the request end.
      res.end();
    });
    
    export default app;
    
    // 2. File: src/util.ts
    import env from 'env-var';
    
    const getAValue = (body: any) => {
      // Need to know whether this function get called.
      console.log('Real getAValue called');
      // This is based on your code.
      const value = env.get('VAR_NAME').required().asString();
      return value;
    };
    
    export { getAValue };
    
    // 3. File: test/index.spec.ts
    import request from 'supertest';
    import app from '../src';
    
    describe('POST /hello', () => {
      it('Returns 200 on expected input', (done) => {
        const payload = {
          'foo':'bar'
        }
    
        request(app)
          .post('/hello')
          .send(payload)
          .expect(200)
          .end((err) => {
            if (err) {
              done(err)
            } else {
              done();
            }
          });
       });
    });
    

    现在是重要文件:test/stubs.ts

    替代 a) 存根 getAValue()

    // 4a File: test/stubs.ts
    import sinon from 'sinon';
    import * as util from '../src/util';
    
    sinon.stub(util, 'getAValue').callsFake((input: any) => {
      console.log('fake getAValue called');
      // Input here is: req.body or payload from test.
      return input;
    });
    

    我从终端运行时的结果:

    $ npm run test
    
    > 69006601@1.0.0 test
    > mocha -r ts-node/register -r test/stubs.ts 'test/**/*.ts' --exit
    
    
    
      POST /hello
    /hello called
    fake getAValue called
    getAValue return: { foo: 'bar' }
        ✔ Returns 200 on expected input
    
    
      1 passing (22ms)
    

    在这个替代方案中,真正的 getAValue 函数永远不会被调用,而假的 getAValue 函数会被调用。您可以在 fake 函数中设置测试环境。

    替代 b) 存根 env.get()

    // 4b File: test/stubs.ts
    import sinon from 'sinon';
    import env from 'env-var';
    
    sinon.stub(env, 'get').callsFake(function (input: any) {
      // Input is VAR_NAME.
      console.log('fake env.get called: ', input);
      // Supply with test env.
      return env.from({ VAR_NAME: 'test' }).get(input);
    });
    

    我从终端运行时的结果:

    $ npm run test
    
    > 69006601@1.0.0 test
    > mocha -r ts-node/register -r test/stubs.ts 'test/**/*.ts' --exit
    
    
    
      POST /hello
    /hello called
    Real getAValue called
    fake env.get called:  VAR_NAME
    getAValue return: test
        ✔ Returns 200 on expected input
    
    
      1 passing (22ms)
    

    在这个替代方案中,真正的 getAValue 会被调用,但真正的 env.get() 不会被调用,因此您可以设置 env 进行测试。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-06-05
      • 1970-01-01
      • 2023-04-11
      • 2017-10-04
      • 2021-11-26
      • 2019-02-03
      • 2015-06-02
      相关资源
      最近更新 更多