繁体   English   中英

如何在 Jest 中模拟每个测试隐式依赖的模块?

[英]How to mock module which depends implicitly per test in Jest?

我有一个集成测试,我对 MongoDB 数据库进行了实际的 DB 调用。 但是为了测试事务是否过期,我需要为该特定 test 模拟数据库 我进行实际数据库调用的原因有很多,我只是为了这个例子才提到状态。

Jest 具有jest.doMock函数,但这仅在我想在测试中导入该函数时有用,但在我的情况下,这是我想在快速中间件中调用时为该特定测试模拟的 DB 函数。

还有另一个选项可以模拟整个../db模块,但这会使我的实际项目中的测试复杂化。 如果我可以模拟特定测试的数据库调用,而其余所有测试应该进行真正的数据库调用,那对我来说将非常容易。

有没有办法在 Jest 中做到这一点?

// a.ts
import express from "express"
import db from "../db";

const app = express()

app.get("/api/deduct-balance/:txn_id", (req, res) => {
  const txn = await db.findById(txn_id)
  
  // return error message if txn expired
  if (txn.exipre_at <= new Date()) {
    return res.status(401).json({ error: "txn expired" });
  }

  // otherwise update the txn state
  txn.state = "DEDUCTED";
  await txn.save()

  return res.status(200).json();
});
// a.test.ts
import db from "../db";

describe("mixed tests", () => {
  test("should make REAL db calls", async () => {
    await axios.get("/api/deduct-balance/123")
    const txn = await db.findById("123");
    expect(txn.state).toBe("DEDUCTED");
  });

  test("should use MOCKED value", async () => {
    // need a way to mock the DB call so that I can return an expired transaction
    // when I hit the API

    const { data } = await axios.get("/api/deduct-balance/123")
    
    expect(data).toBe({
      error: {
        message: "txn expired"
      }
    });
  });
})

对于这种情况,集成测试是多余的。 简单的单元测试就足够了。 它们执行起来很快,只测试一件事,你应该有很多。

因为您将处理程序定义为匿名函数,所以默认情况下很难进行单元测试。 所以第一个动作是通过提取它更容易测试。

// deduct-balance-handlers.ts
export const deductBalanceByTransaction = async (req, res) => {
   const txn = await db.findById(txn_id)

   // return error message if txn expired
   if (txn.exipre_at <= new Date()) {
        return res.status(401).json({ error: "txn expired" });
   }

   // otherwise update the txn state
   txn.state = "DEDUCTED";
   await txn.save()

   return res.status(200).json();
}

它还将使应用程序配置更加干净。

// a.ts
import express from "express"
import db from "../db";
import { deductBalanceByTransaction } from './deduct-balance-handlers';
const app = express()

app.get("/api/deduct-balance/:txn_id", deductBalanceByTransaction);

现在可以轻松地在测试中重用处理程序,而无需依赖 Web 框架或数据库。

// a.test.ts
import db from "../db";
import { deductBalanceByTransaction } from './deduct-balance-handlers';

jest.mock('../db');

describe("deduct-balance", () => {
  test("Expired transaction should respond with 401 status", async () => {
    const response = mockResponse();
    deductBalanceByTransaction(request, response);
    expect(response.status).toBe(401);
  });
})

为简单起见,我在代码中留下了创建模拟响应和模拟模块的部分。 可以在此处了解有关嘲笑的更多信息: https : //jestjs.io/docs/en/manual-mocks

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM