我有一个集成测试,在该测试中我对MongoDB数据库进行了实际的数据库调用。但是为了测试事务是否过期,我需要为该特定测试模拟数据库。我进行实际数据库调用的原因有很多,仅出于本示例的目的,我提到的是状态。
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"
}
});
});
})
答案 0 :(得分:1)
对于这种情况,集成测试是过大的。简单的单元测试就足够了。它们执行起来很快,只测试一件事,所以您应该拥有很多。
由于将处理程序定义为匿名函数,因此默认情况下很难对单元进行测试。因此,第一步是通过提取来简化测试。
// 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