此bounty已结束。回答此问题有资格获得+300声望奖励。奖励宽限期将在4小时后结束。Dycey正在寻找一个规范答案:各种框架都有很多方法,但我似乎找不到任何简单的方法。我真的很想了解这个过程。
我有一个简单的“普通”4文件玩具解决方案。我想为bingo.js认证路由'/'编写一个Jest测试。以下是显示完整设置的四个文件。
index.js
,Express应用根目录routes/auth.js
,一个简单的身份验证POST
端点,用于检查用户routes/bingo.js
,需要对用户进行身份验证的端点,以及middleware/authentication.js
,一个简单的中间件,用于检查会话用户
我正在绞尽脑汁,试图弄清楚如何为bingo.js端点编写单元测试,而不必通过index.js
运行整个应用程序-我不需要完整的端到端测试,这就是Cypress测试的目的。
我试着找到只调用auth步骤的方法,我试着模拟会话,我试着弄清楚如何在Supertest上设置会话。
拜托,至少有人能给我指个路吧?
index.js
// index.js
const express = require("express");
const cookieParser = require("cookie-parser");
const session = require("express-session");
const app = express();
const bingoRouter = require("./routes/bingo");
const authRouter = require("./routes/auth");
// middleware
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(
session({
cookie: { maxAge: 300000 },
store: new session.MemoryStore(),
saveUninitialized: true,
resave: "true",
secret: "our_really_secret_key",
})
);
app.use("/bingo", bingoRouter);
app.use("/auth", authRouter);
app.use((req, res) => {
return res.status(404).json({
error: "Not Found",
});
});
app.listen(port);
module.exports = app;
字符串
auth.js
// routes/auth.js
const express = require("express");
const router = express.Router();
const jwt = require("jsonwebtoken");
const secretKey = "our_really_secret_key";
// Authenticate user
router.post("/login", async (req, res) => {
const { username, password } = req.body;
const user = { username: "username", password: "password", is_admin: true };
if (user && user.password === "password") {
req.session.user = user;
res.redirect("/bingo");
} else {
res.render("auth", { error: "Invalid username or password" });
}
});
型
bingo.js
// routes/bingo
const { isAdmin } = require("../middleware/authentication");
const express = require("express");
const router = express.Router();
router.use(isAdmin);
router.get("/", async function (req, res) {
res.render("bingo", {
user: req.session.user,
});
});
module.exports = router;
型
authentication.js
// middleware/authentication.js
exports.isAdmin = (req, res, next) => {
if (req.session.user && req.session.user.is_admin) {
// User is authenticated & admin, allow access to route
next();
} else {
// User is not authenticated or not admin, redirect to login page
res.redirect("/auth");
}
};
型
2条答案
按热度按时间wyyhbhjk1#
正如morganney在评论中提到的,Nock并不适合您的任务。
它是为HTTP服务器模拟和预期而设计的,主要用于通过拦截传出的HTTP请求并提供编程响应来测试外部服务调用。
虽然它可以用于模拟来自外部服务的响应,但它不能用于Express应用程序中的内部中间件测试,而这正是您所需要的。
您有一个经过身份验证的Express端点:
字符串
您可以使用
supertest
向Express应用发出请求并使用jest
模拟函数或模块来测试它(Jest中的已验证端点)。如果您有身份验证中间件,则通常会模拟会话或中间件来模拟登录用户。另请参阅Francisco Mendes的介绍“Testing Express Api with Jest and Supertest“。
由于您希望隔离测试
bingo.js
端点,因此不需要通过auth.js
路由进行身份验证。相反,您可以直接mockisAdmin
中间件,以便始终调用next()
,就像用户通过身份验证一样。型
如上所述,使用
supertest
向bingo.js
路由发送请求。在测试中,在导入路由器之前模拟isAdmin
中间件。bingo.test.js
:型
这将假定
isAdmin
是访问/bingo
需要传递的唯一中间件。如果有更多中间件层需要mocking,则使用类似的方法。确保使用
--runInBand
标志运行Jest测试,以避免会话处理和并发性问题。如何设置mocking函数来测试未验证的用户是否被重定向?
如何向请求中添加经过身份验证的用户,即将
req.session.user
设置为已知对象?要设置一个将
req.session.user
设置为已知对象的测试,您可以模拟authentication
中间件来将用户添加到req.session
。您的项目看起来像:
型
bingo.test.js
是:型
在任何路由处理之前,
mockSession
被直接注入到req.session
中,这应该有效地模拟经过身份验证的用户的会话。这样,当访问
/bingo
路由时,req.session.user
将被设置为用户已经通过身份验证。wljmcqd82#
要使用Jest和Supertest对
bingo.js
端点进行单元测试,您可以模拟isAdmin
中间件。这种方法允许您模拟经过身份验证的用户,而无需执行实际的身份验证过程。以下是您的操作方法:1.**模拟
isAdmin
中间件:**通过模拟isAdmin
中间件,您可以绕过身份验证检查,直接测试您的bingo.js
路由的行为。模拟将始终调用next()
,模拟通过身份验证的用户。1.测试设置示例:
字符串
此测试检查经过身份验证的用户是否可以访问
/bingo
路由。1.**测试未经身份验证的访问:**要测试未经身份验证的用户的行为,请修改
isAdmin
的mock以模拟身份验证失败,例如,通过重定向到登录页面。1.**添加已知用户:**如果您需要在会话中使用特定的用户对象进行测试,可以修改mock添加
req.session.user
对象。1.**运行测试:**确保使用
--runInBand
标志运行Jest测试,以避免会话处理和并发问题。这种方法将重点放在孤立的
bingo.js
路由上,对于不需要测试整个应用程序流的单元测试场景非常理想。