【问题标题】:fastify, jest: running processes after calling .close() on fastify instancefastify, jest:在 fastify 实例上调用 .close() 后运行进程
【发布时间】:2020-02-25 16:57:19
【问题描述】:

我有以下函数用于打开数据库连接并运行我的 fastify 服务器实例 (server.js)

import fastify from "fastify";
import fastifyCors from "fastify-cors";
import { MongoClient } from "mongodb";

import characterRoute from "./routes/character";
import gearRoute from "./routes/gear";

import CharacterDAO from "./dao/character";
import GearDAO from "./dao/gear";

import { seedData } from "./dataSeed";

let connection;
let serverInstance;

// server startup command
export const startServer = async port => {
  try {
    serverInstance = fastify({ logger: false });
    serverInstance.register(fastifyCors, {
      origin: "*"
    });
    serverInstance.register(characterRoute);
    serverInstance.register(gearRoute);

    await serverInstance.listen(port, "0.0.0.0");
  } catch (err) {
    serverInstance.log.error(err);
    process.exit(1);
  }
};

// server shutdown command
export const killServer = async () => {
  await serverInstance.close();
  console.log("server instance closed");
  await connection.close();
  console.log("db connection closed");
};

// connect mongoDb, seed data if needed, run fastify server
export const runServer = async ({ dbUrl, dbName, environment, port }) => {
  // test seed data when starting server if running a test suite
  if (environment === "test") {
    await seedData({
      hostUrl: dbUrl,
      databaseName: dbName
    });
  }

  connection = await MongoClient.connect(dbUrl, {
    poolSize: 50,
    useNewUrlParser: true,
    useUnifiedTopology: true,
    wtimeout: 2500
  });
  const database = await connection.db(dbName);
  // inject database connection into DAO objects
  CharacterDAO.injectDB(database);
  GearDAO.injectDB(database);
  // start the fastify server
  await startServer(port);
};

现在我想对正在运行的服务器实例运行一些测试,然后退出运行程序。我一直在阅读fastify docs 并试图将设置调整为开玩笑。这是我的测试文件:

import { killServer, runServer } from "../server";

const serverOptions = {
  dbUrl: process.env.dbUrl,
  dbName: process.env.dbName,
  environment: process.env.environment,
  port: process.env.port
};

beforeAll(async () => {
  // run the server instance we are testing against
  await runServer({
    ...serverOptions
  });
});

afterAll(async () => {
  // figure out a way to kill the test server here
  await killServer();
});

但在我的测试完成后,我在控制台中收到以下警告:

Jest did not exit one second after the test run has completed.

This usually means that there are asynchronous operations that weren't stopped in your tests. Consider running Jest with `--detectOpenHandles` to troubleshoot this issue.

而且我必须手动结束测试套件。

这可能是什么原因?我有 .close() 函数似乎在测试套件完成后被正确调用(之后我得到了 console.logs)。

供参考,jestconfig.json

{
  "transform": {
    "^.+\\.(t|j)sx?$": "babel-jest"
  },
  "testRegex": "(/__tests__/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?)$",
  "moduleFileExtensions": ["ts", "tsx", "js", "jsx", "json", "node"]
}

npm 测试脚本(参数省略)

dbUrl=mongodb+srv://saw-dsadw-dsawad@cluster0-dsa.dsa.dsa  dbName=dsa-fwa- environment=test port=4000 npx jest --config jestconfig.json

使用--detectOpenHandles 运行相同的脚本不会提供任何额外的输出。

【问题讨论】:

    标签: node.js jestjs fastify


    【解决方案1】:

    对于任何发现此问题的人,解决方案是重构 server.js 并进行更详细的测试设置:

    server.js

    export const buildFastify = () => {
      const serverInstance = fastify({ logger: false });
      serverInstance.register(fastifyCors, {
        origin: "*"
      });
      serverInstance.register(characterRoute);
      serverInstance.register(gearRoute);
      return serverInstance;
    };
    
    export const buildDbConnection = async ({ dbUrl }) => {
      const connection = await MongoClient.connect(dbUrl, {
        poolSize: 50,
        useNewUrlParser: true,
        useUnifiedTopology: true,
        wtimeout: 2500
      });
      return connection;
    };
    

    .test.js

    const supertest = require("supertest");
    
    import CharacterDAO from "../dao/character";
    import GearDAO from "../dao/gear";
    
    import { buildDbConnection, buildFastify } from "../server";
    
    let connection;
    let database;
    let server;
    
    const serverOptions = {
      dbUrl: process.env.dbUrl,
      dbName: process.env.dbName,
      environment: process.env.environment,
      port: process.env.port
    };
    
    // supertest instance to make server requests
    const supertestInstance = supertest("http://localhost:4000");
    
    beforeAll(async () => {
      // database connection to validate that response data comes from the database
      connection = await buildDbConnection({ dbUrl: serverOptions.dbUrl });
      database = await connection.db(serverOptions.dbName);
    
      // inject db into our DAO classes needed for the server to function properly
      CharacterDAO.injectDB(database);
      GearDAO.injectDB(database);
    
      // run the server instance we are testing against
      server = await buildFastify();
      await server.listen(serverOptions.port, "0.0.0.0");
    });
    
    afterAll(async () => {
      await server.close();
      await connection.close();
    });
    

    所以问题出在复杂的 runServer 函数中 - 在所有测试完成后调用使数据库句柄保持打开状态。

    【讨论】:

    • 我会添加server.server.unref() 以防止保持进程运行。
    • @xamgore 将server.server 传递给supertest 变量时不需要(假设您有const supertest = require('supertest'))。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-12-13
    • 1970-01-01
    • 1970-01-01
    • 2021-12-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多