我在 client/index.js
中有一个函数,它使用 axios 发出请求
import axios from "axios";
const createRequest = async (url, method) => {
const response = await axios({
url: url,
method: method
});
return response;
};
export default { createRequest };
我想使用 jest
测试这个功能,所以我创建了 client/index.test.js
import { jest } from "@jest/globals";
import axios from "axios";
import client from "./";
jest.doMock('axios', () => jest.fn(() => Promise.resolve()));
describe("Client", () => {
it("should call axios and return a response", async () => {
const response = await client.createRequest('http://localhost/', 'GET');
expect(axios).toHaveBeenCalled();
})
})
但是当我尝试运行它时,测试失败了,我收到了这个错误
connect ECONNREFUSED 127.0.0.1:80
如果我使用模拟而不是 doMock,那么我会收到此错误 -
ReferenceError: /Users/project/src/client/index.test.js: The module factory of `jest.mock()` is not allowed to reference any out-of-scope variables.
Invalid variable access: jest
package.json
-
{
"name": "project",
"version": "0.0.1",
"main": "index.js",
"author": "author",
"license": "MIT",
"private": false,
"type": "module",
"scripts": {
"start": "node --experimental-json-modules --experimental-specifier-resolution=node ./src/index.js",
"start:dev": "nodemon --experimental-json-modules --experimental-specifier-resolution=node ./src/index.js",
"test": "node --experimental-vm-modules node_modules/.bin/jest",
"test:dev": "node --experimental-vm-modules node_modules/.bin/jest --watch",
"test:coverage": "node --experimental-vm-modules node_modules/.bin/jest --coverage",
"lint": "eslint --fix .",
"pretty": "prettier --write ."
},
"dependencies": {
"axios": "^0.21.1",
"express": "^4.17.1"
},
"devDependencies": {
"babel-eslint": "^10.1.0",
"eslint": "^7.23.0",
"jest": "^26.6.3",
"prettier": "^2.2.1",
"supertest": "^6.1.3"
},
"jest": { "testEnvironment": "node" }
}
我在节点环境中运行它,节点版本是 14.16.0
,开玩笑的版本是 26.6.3
。请帮助确定这种方法有什么问题以及如何解决它。
原文由 doctorsherlock 发布,翻译遵循 CC BY-SA 4.0 许可协议
我会推荐一种完全不同的方法来解决这个问题。与其尝试模拟 Axios,这是一个 您不拥有的 相对复杂的 API,不如使用
msw
等工具在网络边界进行测试。这使您可以自由重构实现 而无需 更改测试,让您更有信心它仍在工作。你可以这样做:axios.create({ baseURL: "http://localhost", ... })
;node-fetch
)。此外,如果 Axios API 更改,您的测试将开始失败, _告诉您您的代码不再有效_。使用测试替身,因为它仍然会实现以前的 API,所以您会获得通过但具有误导性的测试结果。
这是那种测试的样子;请注意,根本没有提到 Axios,它现在只是一个实现细节,我们只关心 _行为_:
请注意,我不得不使用
.toMatchObject
因为您公开了整个 Axios 响应对象,其中包含很多属性。这对您的客户端来说不是一个好的 API,因为现在 所有 使用客户端的东西都在使用 Axios API;这使您与它严重耦合,并稀释了我上面提到的好处。我不确定您打算如何使用它,但我倾向于完全隐藏传输层的细节——状态代码、标头等内容不太可能与消费者的业务逻辑相关。现在你真的只有:
在这一点上,您的消费者还不如直接使用 Axios。