Jest Spy 说函数未被调用

Cle*_*ent 3 javascript typescript jestjs

我可以知道函数sendResponse被调用,因为里面的 console.log 行sendResponse被执行了。然而,我的间谍说该sendResponse方法没有被调用。只是想知道我在这里做错了什么。

\n\n
import * as ExpressHelpers from \'./express-helper\';\n\ndescribe(\'sendResponse\', () => {\n    it(\'sends a 500 error response\', () => {\n        const sendResponseSpy = spyOn(ExpressHelpers, \'sendResponse\');\n        const mockResponse = () => {\n            const res: any = {};\n            res.status = jest.fn().mockReturnValue(res);\n            res.send = jest.fn().mockReturnValue(res);\n            return res;\n        };\n        const errorMsg = \'Server error msg\';\n        const res = mockResponse();\n        ExpressHelpers.sendServerError(errorMsg, res);\n        expect(sendResponseSpy).toHaveBeenCalled();\n    });\n});\n
Run Code Online (Sandbox Code Playgroud)\n\n
export function sendResponse(statusCode: HttpStatus, message: string, data: {}, response: Express.Response) {\n    const responseEntity: ResponseEntity = {\n        message,\n        statusCode,\n        data,\n    };\n    response.send(responseEntity);\n}\n\nexport function sendServerError(serverErrorMsg: string, res: Express.Response) {\n    sendResponse(HttpStatus.SERVER_ERROR, serverErrorMsg, null, res);\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

错误:

\n\n
  \xe2\x97\x8f Express Helper \xe2\x80\xba sendResponse \xe2\x80\xba sends a 500 error response\n\n    expect(spy).toHaveBeenCalled()\n\n    Expected spy to have been called, but it was not called.\n\n      35 |             const res = mockResponse();\n      36 |             ExpressHelpers.sendServerError(errorMsg, res);\n    > 37 |             expect(sendResponseSpy).toHaveBeenCalled();\n         |                                     ^\n      38 |         });\n      39 |     });\n      40 | });\n\n      at Object.it (src/helpers/express-helper.test.ts:37:37)\n
Run Code Online (Sandbox Code Playgroud)\n

小智 5

Jest 本身并不在 ES 模块上运行,您的代码由 Babel 或 TSC 进行转译,然后加载并执行。这种转译的结果是,导出的函数引用现在绑定到“导出”对象,该对象在源代码中不可见,但存在于正在运行的代码中。

调用spyOn 时,会监视“exports”(exports.sendResponse) 对象内的引用,但不会监视函数调用(sendResponse) 内的引用。一种解决方案是将所有函数绑定到某个导出的对象,如下所示

function foo() { namespace.bar() }
function bar() {}

const namespace = {
    foo,
    bar
}
export default namespace;
Run Code Online (Sandbox Code Playgroud)

如果这感觉像是黑客攻击,您可以使用具有静态方法的类来达到几乎相同的效果。看起来 jest 在不久的将来不会获得 ESM 支持(https://github.com/facebook/jest/issues/4842),所以这将是更简单的解决方案之一。