无法在测试文件中模拟默认导出
Can't mock default export in tested file
我正在开发一个 Typescript 项目,我正在尝试为通过 MongoDB 响应进行排序的函数添加测试以获得有意义的结果。我已经设置了数据库的内存模拟,现在我只需要在 运行 对我的文件中的函数进行测试时以某种方式获得使用这个模拟数据库的测试。
我有一个名为 mongoClient.ts
的文件,它负责我需要模拟的这个 MongoClient 对象:
import { MongoClient } from 'mongodb';
const client = new MongoClient(`${process.env.MONGO_CONNECT}`);
export default client;
我需要测试的文件名为 models.ts
,使用 ES6 导入语句导入 mongoClient
:
import client from '../mongoClient';
在我的测试中,我创建了一个 MongoMemoryServer
(mongodb-memory-server),并且我创建了一个 class 来处理与此 MongoMemoryServer 的连接:
class dbConnection {
server;
connection;
uri;
async init() {
this.server = await MongoMemoryServer.create();
this.uri = await this.server.getUri();
this.connection = await new MongoClient(this.uri);
return this.connection;
}
connect() {
this.connection.connect();
}
getClient() {
return this.connection;
}
getUri() {
return this.uri;
}
async stopIt() {
await this.server.stop();
}
}
我似乎无法获得我在测试中创建的模型对象(使用 const models = require('../src/models');
)来模拟它对 'mongoClient' 的导入。
我试过以下方法:
let mock_db = new dbConnection();
jest.doMock('../src/mongoClient', () => ({
__es6Module: true,
default: mock_db.getClient()
}));
我之前试过用mock(...)
;当我 运行 测试时抛出这个错误:
The module factory of `jest.mock()` is not allowed to reference any out-of-scope variables.
在 beforeAll(...)
中,我可以用虚拟信息填充此数据库,因此我在模型中的函数将 运行 正确,但这些函数看不到模拟内存数据库,因为我无法正确模拟在我的 models.ts 顶部导入的 mongoClient 文件。我不想更改任何不在 .test 文件中的代码来完成此操作,但我无法让此测试环境指向我的模拟内存数据库,同时 运行 宁这些测试。我一定是遗漏了一些关于 doMock 实现的东西,我需要一些帮助来修复它。
- -EDIT_1- - 我认为这可能与我声明事物的顺序有关。 class dbConnection
直接在测试文件顶部的导入项下声明。然后在此之下,我将 dbConnection class 实例化为 mockDb 和 jest.doMock(...
,如上例所示。我测试的函数似乎在尝试使用仅包含以下内容的模拟导入:
{"__es6Module":true}
此时我收到的错误消息是 ERROR --- _get__(...).db is not a function
。
这个问题可能是它正确地模拟了导入的模块,但是当它在文件顶部附近的 doMock 语句中声明时,用于模拟 (mockDb.getClient()
) 的默认导出是未定义的。我不知道该把 doMock 移到哪里,如果我将它移到顶层 beforeAll 或移到这些测试的描述部分或测试本身,它就会中断。
- -EDIT_2- - 将__es6Module
改为__esModule
(因为编译后的js文件找__esModule)使得 undefined
是我代码中导入的 class 的内容。
编译后的js代码在顶部有如下内容:
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
const mongoClient_1 = __importDefault(require("../util/mongoClient"));
- -FINAL_EDIT- - 我已经弄清楚了,这是我在 Jest 测试的执行顺序方面的一个错误。我模拟的默认导出客户端在测试 运行 之前尚未初始化。这要求我在每个 'describe' 测试块内的 beforeAll(...)
语句中模拟默认导入,并且在每个测试中我必须在测试开始时使用 [=32= 实例化一个新模型].我现在有工作测试,生活中一切都很好 ;-)
我已经弄清楚了,这是我在 Jest 测试的执行顺序方面的错误。我模拟的默认导出客户端在测试 运行 之前尚未初始化。这要求我在每个 'describe' 测试块内的 beforeAll(...) 语句中模拟默认导入,并且在每个测试中我必须在测试开始时使用 const models = 实例化一个新模型要求(...);。我现在有工作测试
我正在开发一个 Typescript 项目,我正在尝试为通过 MongoDB 响应进行排序的函数添加测试以获得有意义的结果。我已经设置了数据库的内存模拟,现在我只需要在 运行 对我的文件中的函数进行测试时以某种方式获得使用这个模拟数据库的测试。
我有一个名为 mongoClient.ts
的文件,它负责我需要模拟的这个 MongoClient 对象:
import { MongoClient } from 'mongodb';
const client = new MongoClient(`${process.env.MONGO_CONNECT}`);
export default client;
我需要测试的文件名为 models.ts
,使用 ES6 导入语句导入 mongoClient
:
import client from '../mongoClient';
在我的测试中,我创建了一个 MongoMemoryServer
(mongodb-memory-server),并且我创建了一个 class 来处理与此 MongoMemoryServer 的连接:
class dbConnection {
server;
connection;
uri;
async init() {
this.server = await MongoMemoryServer.create();
this.uri = await this.server.getUri();
this.connection = await new MongoClient(this.uri);
return this.connection;
}
connect() {
this.connection.connect();
}
getClient() {
return this.connection;
}
getUri() {
return this.uri;
}
async stopIt() {
await this.server.stop();
}
}
我似乎无法获得我在测试中创建的模型对象(使用 const models = require('../src/models');
)来模拟它对 'mongoClient' 的导入。
我试过以下方法:
let mock_db = new dbConnection();
jest.doMock('../src/mongoClient', () => ({
__es6Module: true,
default: mock_db.getClient()
}));
我之前试过用mock(...)
;当我 运行 测试时抛出这个错误:
The module factory of `jest.mock()` is not allowed to reference any out-of-scope variables.
在 beforeAll(...)
中,我可以用虚拟信息填充此数据库,因此我在模型中的函数将 运行 正确,但这些函数看不到模拟内存数据库,因为我无法正确模拟在我的 models.ts 顶部导入的 mongoClient 文件。我不想更改任何不在 .test 文件中的代码来完成此操作,但我无法让此测试环境指向我的模拟内存数据库,同时 运行 宁这些测试。我一定是遗漏了一些关于 doMock 实现的东西,我需要一些帮助来修复它。
- -EDIT_1- - 我认为这可能与我声明事物的顺序有关。 class dbConnection
直接在测试文件顶部的导入项下声明。然后在此之下,我将 dbConnection class 实例化为 mockDb 和 jest.doMock(...
,如上例所示。我测试的函数似乎在尝试使用仅包含以下内容的模拟导入:
{"__es6Module":true}
此时我收到的错误消息是 ERROR --- _get__(...).db is not a function
。
这个问题可能是它正确地模拟了导入的模块,但是当它在文件顶部附近的 doMock 语句中声明时,用于模拟 (mockDb.getClient()
) 的默认导出是未定义的。我不知道该把 doMock 移到哪里,如果我将它移到顶层 beforeAll 或移到这些测试的描述部分或测试本身,它就会中断。
- -EDIT_2- - 将__es6Module
改为__esModule
(因为编译后的js文件找__esModule)使得 undefined
是我代码中导入的 class 的内容。
编译后的js代码在顶部有如下内容:
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
const mongoClient_1 = __importDefault(require("../util/mongoClient"));
- -FINAL_EDIT- - 我已经弄清楚了,这是我在 Jest 测试的执行顺序方面的一个错误。我模拟的默认导出客户端在测试 运行 之前尚未初始化。这要求我在每个 'describe' 测试块内的 beforeAll(...)
语句中模拟默认导入,并且在每个测试中我必须在测试开始时使用 [=32= 实例化一个新模型].我现在有工作测试,生活中一切都很好 ;-)
我已经弄清楚了,这是我在 Jest 测试的执行顺序方面的错误。我模拟的默认导出客户端在测试 运行 之前尚未初始化。这要求我在每个 'describe' 测试块内的 beforeAll(...) 语句中模拟默认导入,并且在每个测试中我必须在测试开始时使用 const models = 实例化一个新模型要求(...);。我现在有工作测试