node.js - 在 Express 路由的 Mocha 单元测试中使用 Sinon 存根环境变量
问题描述
我正在努力做到这一点,所以在我的 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);
test
并在我的脚本中使用我的脚本package.json
来查找这些存根
"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 路由测试模拟环境变量的正确方法是什么?
解决方案
在您的情况下,我有 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 函数会被调用。您可以在假函数中设置测试环境。
替代 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 进行测试。
推荐阅读
- go - 如何初始化特定的结构格式
- verilog - 在 Verilog 中为输出添加延迟
- node.js - 使用 node.js 安装 mysql 模块时出现问题
- java - 返回 json 格式响应
- android - 使用 Post Not Get 的分页库 - 未填充适配器
- javascript - NativeScript 和串口?
- android - 在 firebase 中返回对象的属性返回 null
- ajax - Ajax 请求关闭 MVC 表单
- javascript - 在 Wordpress Gutenberg 自定义块中显示自定义帖子类型列表
- python - 使用 Python Flask sqlalchemy orm 在 PostgreSQL 中加入查询