Chai 测试没有通过 cookie 认证中间件

Chai test doesn't pass the cookie authentification middleware

我有一个中间件可以在让用户访问路由之前检查用户是否已登录。它看起来像这样:

import { Request, Response, NextFunction } from "express";
import jwt from "jsonwebtoken";

const authenticate = (req: Authenticate, res: Response, next: NextFunction) => {
  const token = req.cookies; 
  if (token) {
    jwt.verify(token, process.env.JWT_TOKEN_KEY, (error, res) => {
      if (error) return res.sendStatus(403);
      req.cookie = { _id: res._id, locale: res.locale };
      return next();
    });
  }
  return res.sendStatus(401);
};

export default authenticate;

测试是:

import chai from "chai";
import chaiHttp from "chai-http";
import { server } from "../index";

chai.use(chaiHttp);
const api = chai.request(server).keepOpen();

describe("GET /user/:id", () => {
  it("return user information", () => {
    api
      .get("/user/123")
      .set("Cookie", "_id=567;locale=en")
      .end(function (err, res) {
        chai.expect(res).to.have.status(200);
      });
  });
});

如果我从路由中删除中间件,测试工作正常。所以:

// OK
router.post("/user/:id", searchUser);

// NOT OK
router.post("/user/:id", authenticate, searchUser);

错误是:

TypeError: Cannot read property 'sendStatus' of undefined at /Users/myname/Desktop/Code/myapp/server/src/middleware/authenticate.ts:21:29 at Object.module.exports [as verify] (/Users/myname/Desktop/Code/myapp/server/node_modules/jsonwebtoken/verify.js:57:12)

jwt.verify() 回调函数的 res 变量覆盖了 authenticate 中间件的 res 变量,这就是你得到这个错误的原因。你应该给它一个不同的名字以避免冲突。

我想你从 chai-http 得到了 req.cookies。如果没有,您可能忘记使用 cookie-parser 中间件。

例如

index.ts:

import express from 'express';
import cookieParser from 'cookie-parser';
import authenticate from './mws/authenticate';

const server = express();

server.use(cookieParser());
server.get('/user/:id', authenticate, (req, res) => {
  const { id } = req.params;
  res.json({ id, name: 'teresa teng' });
});

export { server };

authenticate.ts:

import { Request, Response, NextFunction } from 'express';
import jwt from 'jsonwebtoken';

const authenticate = (req: Request, res: Response, next: NextFunction) => {
  const token = req.cookies;
  console.log('cookies: ', req.cookies);
  if (token) {
    jwt.verify(token, process.env.JWT_TOKEN_KEY, (error, verifyResponse) => {
      if (error) return res.sendStatus(403);
      req.cookies = { _id: verifyResponse._id, locale: verifyResponse.locale };
      return next();
    });
  }
  return res.sendStatus(401);
};

export default authenticate;

index.test.ts:

import chai from 'chai';
import chaiHttp from 'chai-http';
import { server } from './';

chai.use(chaiHttp);
const api = chai.request(server).keepOpen();

describe('GET /user/:id', () => {
  it('return user information', (done) => {
    api
      .get('/user/123')
      .set('Cookie', '_id=567;locale=en')
      .end(function (err, res) {
        chai.expect(res).to.have.status(200);
        done();
      });
  });
});

日志:

  GET /user/:id
cookies:  { _id: '567', locale: 'en' }
    1) return user information