表达Jest和Supertest如何用argument模拟中间件



我已经试着用Jest、Supertest和Express测试我的rest api的一个端点好几个小时了。

该端点由名为"的认证中间件保护;advancedAuthGuard";。

所以我试图模拟这个中间件,以便跳过端点测试的身份验证检查

//./router.js 
router.get('/route1', advancedAuthGuard(false), controller);

重要提示:advancedAuthGuard是一个中间件,它接受配置参数(当前中间件(

//./middleware/advancedAuthGuard.js
const advancedAuthGuard = (additionalCondition) => (req,res,next) => {
//Check authentication logic ...
const isAuth = true
if (isAuth && !additionalCondition)
next()
else
next(new Error('Please auth'))
}

当我运行以下测试以检查我是否得到状态代码"200"时。测试在运行前失败。

//./test.js
import supertest from "supertest"
import app from './app.js'
import { advancedAuthGuard } from "./middlewares/advancedAuthGuard";
jest.mock("./middlewares/advancedAuthGuard")
const request = supertest(app)
beforeEach(()=>{
jest.clearAllMocks()
})
it("should '/route1' respond with 200 status", async ()=>{
const mockedMiddleware = jest.fn().mockImplementation((res, req, next)=> next() )
advancedAuthGuard.mockReturnValue(mockedMiddleware)
const res = await request.get("/route1")
expect(res.status).toEqual(200)
})

我得到以下错误:

Test suite failed to run
Route.get() requires a callback function but got a [object Undefined]

> 10 | router.get('/route1', advancedAuthGuard(false), controller);
|        ^

因此,我推断问题来自模拟

当我通过console.log调试它时,我意识到我得到了一个不完整的mock:

  • 我能够验证函数的mock(advancedAuthGuard(false)(是否存在
  • 但是这个mock应该返回function (req,res,next){}类型的第二个mock,但是它只返回未定义

我还注意到:

  • 这个模拟问题只发生在当前的中间件(带有输入参数的中间件(中
  • 只有当在express路由器中执行当前的中间件时,才会出现这种模拟问题。(当我尝试mock外部express路由器时,mock显示正确(

所以我想知道为什么我不可能用Jest和Supertest来模拟Expressjs端点中使用的curried中间件(带参数的中间件(。

这里有一个github链接,具有最小的express、jest、supertest配置,您可以通过运行test.js文件来重现这个问题。https://github.com/enzo-cora/jest-mock-middleware

不确定为什么它没有按照您尝试的方式工作,但如果您将mock实现传递给autoMock函数,它就会成功。

import supertest from "supertest";
import app from "./app";

jest.mock("./middlewares/simpleAuthGuard", () => ({
simpleAuthGuard: (_, __, next) => next()
}));
jest.mock("./middlewares/advancedAuthGuard", () => ({
advancedAuthGuard: () => (_, __, next) => next()
}));
const request = supertest(app);
describe('My tests', () => {
beforeEach(() => jest.clearAllMocks());
it("should '/route1' with advanced middleware work", async () => {
const res = await request.get("/route1");
expect(res.status).toEqual(200);
});
it("should '/route2' with simple middleware work", async () => {
const res = await request.get("/route2")
expect(res.status).toEqual(200)
});
});

最新更新