【问题标题】:Jest hangs in i18n.configure()玩笑挂在 i18n.configure()
【发布时间】:2020-05-17 13:35:17
【问题描述】:

我正在使用 Node.jsexpress 构建一个 Restfull API,并决定使用 JestSupertest 测试我的应用程序,在我的 App 类中,我需要一些 i18n 配置(i18n 是用于翻译的库)。

当运行常规快递服务器并使用 InsomniaPostman 手动测试我的路线时,一切正常。但是当我尝试为 /login 路由创建测试时,测试运行良好并且我得到了预期的结果,但 Jest 从未完成运行,它显示 Jest has detected the following 1 open handle potentially keeping Jest from exiting。从它所指出的来看,似乎是对 i18n.configure(... 的调用留下了一个打开的句柄,这很有趣,我检查了 configure 方法,它不是异步的。

这是控制台输出:

这是我的 App.js 文件:

require("dotenv").config({
  path: process.env.NODE_ENV === "test" ? ".env.test" : ".env"
});
const express = require("express");
const cookieParser = require("cookie-parser");

class AppController {
  constructor() {
    this.express = express();
    this.configure();
    this.middlewares();
    this.routes();
  }

  async configure() {
    this.i18n = require("./config/i18n");
  }

  middlewares() {
    this.express.use(express.json());
    this.express.use(cookieParser());
    this.express.use(this.i18n.init);
  }

  routes() {
    this.express.use(require("./routes"));
  }
}

module.exports = new AppController().express;

i18n 配置文件:

const i18n = require("i18n");

i18n.configure({
  locales: ["pt-br", "en-us"],
  defaultLocale: "pt-br",
  cookie: "locale",
  directory: "./locales",
  autoReload: true
});
i18n.setLocale("pt-br");

module.exports = i18n;

测试本身:

const request = require("supertest");    
const app = require("../../src/app.js");

describe("Authentication", () => {

  it("should not authenticate when user does not exist", async () => {
    const response = await request(app)
      .post("/login")
      .send({
        username: "john",
        password: "123123"
      });

    expect(response.status).toBe(401);
  });
});

/login 路由(它在登录文件夹中,这就是为什么我可以只为路由声明“/”):

const routes = require("express").Router();

const LoginController = require("../app/controllers/LoginController");

routes.post("/", LoginController.index);

module.exports = routes;

具有索引功能的LoginController

const passport = require("../../app/middlewares/passport");
const jwt = require("jsonwebtoken");

class LoginController {
  async index(req, res) {
    passport.authenticate("local", { session: false }, (error, user) => {
      if (error || !user) {
        res.status(401).send(res.__(error));
      } else {
        const payload = {
          username: user.username,
          expires: Date.now() + parseInt(process.env.JWT_EXPIRATION_MS)
        };

        req.login(payload, { session: false }, error => {
          if (error) {
            res.status(400).send({ error });
          }

          const token = jwt.sign(
            JSON.stringify(payload),
            process.env.APP_SECRET
          );

          res.cookie("jwt", token, { httpOnly: true, secure: true });
          res.status(200).send({ username: user.username });
        });
      }
    })(req, res);
  }
}

module.exports = new LoginController();

以防万一,这里是护照策略:

const passport = require("passport");
const LocalStrategy = require("passport-local").Strategy;
const passportJWT = require("passport-jwt");
const JWTStrategy = passportJWT.Strategy;

const { User } = require("../models");

passport.use(
  new LocalStrategy(async (username, password, done) => {
    try {
      const user = await User.findOne({ where: { username } });
      let passwordsMatch = false;
      if (user) {
        passwordsMatch = await user.checkPassword(password);
      }

      if (passwordsMatch) {
        return done(null, user);
      } else {
        return done("Incorrect username and/or password");
      }
    } catch (error) {
      done(error);
    }
  })
);

passport.use(
  new JWTStrategy(
    {
      jwtFromRequest: req => req.headers.authorization.split(" ")[1],
      secretOrKey: process.env.APP_SECRET
    },
    (jwtPayload, done) => {
      if (Date.now() > jwtPayload.expires) {
        return done("jwt expired");
      }

      return done(null, jwtPayload);
    }
  )
);

module.exports = passport;

【问题讨论】:

    标签: node.js express jestjs supertest


    【解决方案1】:

    在将 i18n-node 与 jest 一起使用时,您需要禁用 autoReload 选项。我觉得和这个打开的issue有关。

    试试这样的:

    i18n.configure({
      locales: ["pt-br", "en-us"],
      defaultLocale: "pt-br",
      cookie: "locale",
      directory: "./locales",
      autoReload: false
    });
    

    或者如果您的 NODE_ENV 变量等于 "test"

    i18n.configure({
      locales: ["pt-br", "en-us"],
      defaultLocale: "pt-br",
      cookie: "locale",
      directory: "./locales",
      autoReload: process.env.NODE_ENV !== "test"
    });
    

    它对我有用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-11-10
      • 1970-01-01
      • 2020-11-22
      • 1970-01-01
      • 2018-07-28
      • 2019-01-02
      • 2021-06-20
      相关资源
      最近更新 更多