如何使用 Chai 和 Mocha 进行 Google 云功能单元测试
How to use Chai and Mocha for Google Cloud functions unit testing
使用 Chai、Mocha 和 Sinon 为 Google Cloud Function 编写简单单元测试时遇到问题,虽然我指的是 Google unit testing reference doc 但无法理解。
问题
- 我在 运行 单元测试时收到以下错误消息。
TypeError: response.status is not a function
- 为什么我需要在调用函数时对 Request 和 Response 对象进行类型转换?在 Google 文档示例 (Github) 中,他们没有进行类型转换。
onCalculate(req as Request, res as unknown as Response);
Objective:
测试应该通过
onCalculate.ts
import * as functions from "firebase-functions";
export const onCalculate = functions.https.onRequest((request, response) => {
const param1 = request.body.param1;
const param2 = request.body.param2;
response.status(200).send(calculate(param1 as number, param2 as number));
});
/**
* Function to calculate two numbers
* @param {number} param1
* @param {number} param2
* @return {number}
*/
function calculate(param1: number, param2: number): number {
return param1 + param2;
}
onCalculate.spec.ts
import firebase from "firebase-functions-test";
import { Request, Response } from "firebase-functions";
import { stub } from "sinon";
import { assert } from "chai";
import { onCalculate } from "./onCalculate";
const test = firebase();
describe("Calculate", () => {
after(() => {
test.cleanup();
});
it("should return 3", () => {
const req = {
query: {},
body: {
param1: 1,
param2: 2,
},
};
const res = { send: stub() };
onCalculate(req as Request, res as unknown as Response);
assert.ok(res.send.calledOnce);
});
});
您应该对 res.status()
方法进行 stub,因为 res.status(xxx).send()
是方法链调用,您需要使用 sinon.stub().returnsThis()
来实现。
Sinon.JS 附带了一组断言,这些断言反映了间谍和存根上的大多数行为验证方法和属性,这就足够了。请参阅 assertions,因此您不需要使用 chai
包中的 assert
。
req
和res
是mock对象,只包含我们测试需要的属性和方法。对 Request
和 Response
接口不完全满意,所以我们需要使用类型断言来告诉 TSC——“这两个对象的形状是正确的”。官方repo使用的是JS,不是TS。
例如
onCalculate.ts
:
import * as functions from 'firebase-functions';
export const onCalculate = functions.https.onRequest((request, response) => {
const param1 = request.body.param1;
const param2 = request.body.param2;
response.status(200).send(calculate(param1 as number, param2 as number));
});
/**
* Function to calculate two numbers
* @param {number} param1
* @param {number} param2
* @return {number}
*/
function calculate(param1: number, param2: number): number {
return param1 + param2;
}
onCalculate.spec.ts
:
import firebase from 'firebase-functions-test';
import { Request, Response } from 'firebase-functions';
import sinon from 'sinon';
import { onCalculate } from './onCalculate';
const test = firebase();
describe('Calculate', () => {
after(() => {
test.cleanup();
});
it('should return 3', () => {
const req = {
query: {},
body: {
param1: 1,
param2: 2,
},
};
const res = { status: sinon.stub().returnsThis(), send: sinon.stub() };
onCalculate(req as Request, (res as unknown) as Response);
sinon.assert.calledWithExactly(res.status, 200);
sinon.assert.calledWithExactly(res.send, 3);
});
});
测试结果:
Calculate
✓ should return 3
1 passing (4ms)
---------------------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
---------------------|---------|----------|---------|---------|-------------------
All files | 100 | 100 | 100 | 100 |
onCalculate.spec.ts | 100 | 100 | 100 | 100 |
onCalculate.ts | 100 | 100 | 100 | 100 |
---------------------|---------|----------|---------|---------|-------------------
使用 Chai、Mocha 和 Sinon 为 Google Cloud Function 编写简单单元测试时遇到问题,虽然我指的是 Google unit testing reference doc 但无法理解。
问题
- 我在 运行 单元测试时收到以下错误消息。
TypeError: response.status is not a function
- 为什么我需要在调用函数时对 Request 和 Response 对象进行类型转换?在 Google 文档示例 (Github) 中,他们没有进行类型转换。
onCalculate(req as Request, res as unknown as Response);
Objective: 测试应该通过
onCalculate.ts
import * as functions from "firebase-functions";
export const onCalculate = functions.https.onRequest((request, response) => {
const param1 = request.body.param1;
const param2 = request.body.param2;
response.status(200).send(calculate(param1 as number, param2 as number));
});
/**
* Function to calculate two numbers
* @param {number} param1
* @param {number} param2
* @return {number}
*/
function calculate(param1: number, param2: number): number {
return param1 + param2;
}
onCalculate.spec.ts
import firebase from "firebase-functions-test";
import { Request, Response } from "firebase-functions";
import { stub } from "sinon";
import { assert } from "chai";
import { onCalculate } from "./onCalculate";
const test = firebase();
describe("Calculate", () => {
after(() => {
test.cleanup();
});
it("should return 3", () => {
const req = {
query: {},
body: {
param1: 1,
param2: 2,
},
};
const res = { send: stub() };
onCalculate(req as Request, res as unknown as Response);
assert.ok(res.send.calledOnce);
});
});
您应该对 res.status()
方法进行 stub,因为 res.status(xxx).send()
是方法链调用,您需要使用 sinon.stub().returnsThis()
来实现。
Sinon.JS 附带了一组断言,这些断言反映了间谍和存根上的大多数行为验证方法和属性,这就足够了。请参阅 assertions,因此您不需要使用 chai
包中的 assert
。
req
和res
是mock对象,只包含我们测试需要的属性和方法。对 Request
和 Response
接口不完全满意,所以我们需要使用类型断言来告诉 TSC——“这两个对象的形状是正确的”。官方repo使用的是JS,不是TS。
例如
onCalculate.ts
:
import * as functions from 'firebase-functions';
export const onCalculate = functions.https.onRequest((request, response) => {
const param1 = request.body.param1;
const param2 = request.body.param2;
response.status(200).send(calculate(param1 as number, param2 as number));
});
/**
* Function to calculate two numbers
* @param {number} param1
* @param {number} param2
* @return {number}
*/
function calculate(param1: number, param2: number): number {
return param1 + param2;
}
onCalculate.spec.ts
:
import firebase from 'firebase-functions-test';
import { Request, Response } from 'firebase-functions';
import sinon from 'sinon';
import { onCalculate } from './onCalculate';
const test = firebase();
describe('Calculate', () => {
after(() => {
test.cleanup();
});
it('should return 3', () => {
const req = {
query: {},
body: {
param1: 1,
param2: 2,
},
};
const res = { status: sinon.stub().returnsThis(), send: sinon.stub() };
onCalculate(req as Request, (res as unknown) as Response);
sinon.assert.calledWithExactly(res.status, 200);
sinon.assert.calledWithExactly(res.send, 3);
});
});
测试结果:
Calculate
✓ should return 3
1 passing (4ms)
---------------------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
---------------------|---------|----------|---------|---------|-------------------
All files | 100 | 100 | 100 | 100 |
onCalculate.spec.ts | 100 | 100 | 100 | 100 |
onCalculate.ts | 100 | 100 | 100 | 100 |
---------------------|---------|----------|---------|---------|-------------------