用于身份验证的异步中间件的开玩笑测试
Jest testing of async middleware for authentication
在使用实际的 postgres 数据库和一些 fetch()
-ing 代码进行重构之前,我使用静态数组来构建用户 table。目前,测试工作正常,但显然它们是同步工作的。这是占位符 API 代码:
// UserAPI.js
let findUserById = (credentials = {}) => {
const { userId } = credentials
if (userId) {
const foundUser = users.find(user => user.id === userId)
if (foundUser !== undefined) {
const { password: storedpassword, ...user } = foundUser
return user
}
}
return null
}
exports.byId = findUserById
并举例测试如下:
// excerpt from TokenAuth.test.js
const UserAPI = require('../lib/UserAPI')
describe('With TokenAuth middleware', () => {
beforeEach(() => {
setStatus(0)
})
it('should add user to req on authorised requests', () => {
const token = createToken(fakeUser)
const authReq = { headers: { authorization: 'Bearer ' + token } }
const myMiddleware = TokenAuth(UserAPI.byId)
myMiddleware(authReq, fakeRes, fakeNext)
// expect(authReq.user).toStrictEqual({ id: 1, username: 'smith@example.com' });
expect(authReq.user.username).toStrictEqual('smith@example.com')
expect(authReq.user.id).toStrictEqual(1)
})
})
这 运行 没问题,连同其他测试提供了我想要的覆盖范围。但是,我现在想检查测试是否会处理我将用于正确 UserAPI.js
文件的 fetch()
代码的 async/await
性质。所以我将占位符代码重写为:
// UserAPI.js with added async/await pauses ;-)
let findUserById = async (credentials = {}) => {
const { userId } = credentials
// simulate url resolution
await new Promise(resolve => setTimeout(() => resolve(), 100)) // avoid jest open handle error
if (userId) {
const foundUser = users.find(user => user.id === userId)
if (foundUser !== undefined) {
const { password: storedpassword, ...user } = foundUser
return user
}
}
return null
}
exports.byId = findUserById
...此时我开始遇到一些可爱的失败,因为我认为它正在返回未解决的承诺。
我的问题有两个:
我应该如何更改 UserAPI.test.js
测试以应对 findUserByCredentials()
的新 async
性质?
我认为 ExpressJS 对异步函数作为请求处理程序感到满意吗?具体来说,由于 UserAPI.findUserByCredentials
的 async
性质,这样可以吗?
Main App.js
使用 curried UserAPI.byId()
作为 findUserById
.
// App.js (massively simplified)
const express = require('express')
const TokenAuth = require('./middleware/TokenAuth')
const RequireAuth = require('./middleware/RequireAuth')
const UserAPI = require('./lib/UserAPI')
let router = express.Router()
const app = express()
app.use(TokenAuth(UserAPI.byId))
app.use(RequireAuth)
app.use('/users', UserRouter)
module.exports = app
我的 TokenAuth 中间件现在会 运行 按照这些行:
// TokenAuth.js (simplified)
const jwt = require('jsonwebtoken')
require('dotenv').config()
const signature = process.env.SIGNATURE
let TokenAuth = findUserById => async (req, res, next) => {
let header = req.headers.authorization || ''
let [type, token] = header.split(' ')
if (type === 'Bearer') {
let payload
try {
payload = jwt.verify(token, signature)
} catch (err) {
res.sendStatus(401)
return
}
let user = await findUserById(payload)
if (user) {
req.user = user
} else {
res.sendStatus(401)
return
}
}
next()
}
module.exports = TokenAuth
部分回答我们只是在 middleware
调用中添加一个 async/await:
it('should add user to req on authorised requests', async () => {
const token = createToken(fakeUser)
const authReq = { headers: { authorization: 'Bearer ' + token } }
const myMiddleware = TokenAuth(UserAPI.byId)
await myMiddleware(authReq, fakeRes, fakeNext)
// expect(authReq.user).toStrictEqual({ id: 1, username: 'smith@example.com' });
expect(authReq.user.username).toStrictEqual('smith@example.com')
expect(authReq.user.id).toStrictEqual(1)
})
在使用实际的 postgres 数据库和一些 fetch()
-ing 代码进行重构之前,我使用静态数组来构建用户 table。目前,测试工作正常,但显然它们是同步工作的。这是占位符 API 代码:
// UserAPI.js
let findUserById = (credentials = {}) => {
const { userId } = credentials
if (userId) {
const foundUser = users.find(user => user.id === userId)
if (foundUser !== undefined) {
const { password: storedpassword, ...user } = foundUser
return user
}
}
return null
}
exports.byId = findUserById
并举例测试如下:
// excerpt from TokenAuth.test.js
const UserAPI = require('../lib/UserAPI')
describe('With TokenAuth middleware', () => {
beforeEach(() => {
setStatus(0)
})
it('should add user to req on authorised requests', () => {
const token = createToken(fakeUser)
const authReq = { headers: { authorization: 'Bearer ' + token } }
const myMiddleware = TokenAuth(UserAPI.byId)
myMiddleware(authReq, fakeRes, fakeNext)
// expect(authReq.user).toStrictEqual({ id: 1, username: 'smith@example.com' });
expect(authReq.user.username).toStrictEqual('smith@example.com')
expect(authReq.user.id).toStrictEqual(1)
})
})
这 运行 没问题,连同其他测试提供了我想要的覆盖范围。但是,我现在想检查测试是否会处理我将用于正确 UserAPI.js
文件的 fetch()
代码的 async/await
性质。所以我将占位符代码重写为:
// UserAPI.js with added async/await pauses ;-)
let findUserById = async (credentials = {}) => {
const { userId } = credentials
// simulate url resolution
await new Promise(resolve => setTimeout(() => resolve(), 100)) // avoid jest open handle error
if (userId) {
const foundUser = users.find(user => user.id === userId)
if (foundUser !== undefined) {
const { password: storedpassword, ...user } = foundUser
return user
}
}
return null
}
exports.byId = findUserById
...此时我开始遇到一些可爱的失败,因为我认为它正在返回未解决的承诺。
我的问题有两个:
我应该如何更改
UserAPI.test.js
测试以应对findUserByCredentials()
的新async
性质?我认为 ExpressJS 对异步函数作为请求处理程序感到满意吗?具体来说,由于
UserAPI.findUserByCredentials
的async
性质,这样可以吗?
Main App.js
使用 curried UserAPI.byId()
作为 findUserById
.
// App.js (massively simplified)
const express = require('express')
const TokenAuth = require('./middleware/TokenAuth')
const RequireAuth = require('./middleware/RequireAuth')
const UserAPI = require('./lib/UserAPI')
let router = express.Router()
const app = express()
app.use(TokenAuth(UserAPI.byId))
app.use(RequireAuth)
app.use('/users', UserRouter)
module.exports = app
我的 TokenAuth 中间件现在会 运行 按照这些行:
// TokenAuth.js (simplified)
const jwt = require('jsonwebtoken')
require('dotenv').config()
const signature = process.env.SIGNATURE
let TokenAuth = findUserById => async (req, res, next) => {
let header = req.headers.authorization || ''
let [type, token] = header.split(' ')
if (type === 'Bearer') {
let payload
try {
payload = jwt.verify(token, signature)
} catch (err) {
res.sendStatus(401)
return
}
let user = await findUserById(payload)
if (user) {
req.user = user
} else {
res.sendStatus(401)
return
}
}
next()
}
module.exports = TokenAuth
部分回答我们只是在 middleware
调用中添加一个 async/await:
it('should add user to req on authorised requests', async () => {
const token = createToken(fakeUser)
const authReq = { headers: { authorization: 'Bearer ' + token } }
const myMiddleware = TokenAuth(UserAPI.byId)
await myMiddleware(authReq, fakeRes, fakeNext)
// expect(authReq.user).toStrictEqual({ id: 1, username: 'smith@example.com' });
expect(authReq.user.username).toStrictEqual('smith@example.com')
expect(authReq.user.id).toStrictEqual(1)
})