我是Jest和代码测试的新手。我想测试一个使用mongoose从mongodb数据库检索数据的函数。当我运行测试时,我正在测试的函数中对db的所有调用均返回null。测试需要从数据库检索数据的功能的推荐方法是什么?
让我知道您是否需要代码示例或更多信息。
这是我的代码:
code.js
...
function buildText(listing, messageRule, reservation, isReview = false, isLastMinuteMessage = false) {
return new Promise(async function(resolve) {
const name = reservation.name;
try {
message = await Message.findOne({
listingID: listing._id,
messageRuleID: messageRule._id,
reservationID: reservation._id,
message: {$exists: true}
});
} catch (error) {
console.error(error);
}
if (message) {
text = message.message;
} else {
text = messageRule.message;
if (isLastMinuteMessage) {
text = messageRule.lastMinuteMessage;
}
}
text = text.replace(/{{Guest Name}}/g, name);
resolve(text);
});
}
...
code.test.js
const Code = require("./code");
describe("funcs", () => {
it("buildText", async () => {
let listing = {
_id: "1324",
pricingEnabled: true,
listingFound: true,
hideListing: null
};
let messageRule = {
_id: "3452345",
minNights: 1,
reviewEnabled: false,
disableMessageAfterReview: false,
message: 'test',
lastMinuteMessage: 'test2'
};
let reservation = {
_id: "63452345",
hasLeftReview: true,
hasIssues: false
};
let isReview = false;
let isLastMinuteMessage = false;
let response = await Code.buildText(listing, messageRule, reservation, isReview, isLastMinuteMessage);
expect(response).toMatchSnapshot();
});
});
我遇到的麻烦是代码文件中的message = await Message.findOne({
行。它总是返回null,但我需要能够告诉它返回true或false。我该怎么办?
答案 0 :(得分:1)
这是一个基于提供的代码的简单工作示例:
code.js
const { Message } = require('./message');
function buildText(listing, messageRule, reservation, isReview = false, isLastMinuteMessage = false) {
return new Promise(async function (resolve) {
let message, text;
const name = reservation.name;
try {
message = await Message.findOne({
listingID: listing._id,
messageRuleID: messageRule._id,
reservationID: reservation._id,
message: { $exists: true }
});
} catch (error) {
console.error(error);
}
if (message) {
text = message.message;
} else {
text = messageRule.message;
if (isLastMinuteMessage) {
text = messageRule.lastMinuteMessage;
}
}
text = text.replace(/{{Guest Name}}/g, name);
resolve(text);
});
}
module.exports = {
buildText
}
code.test.js
const Code = require('./code');
const { Message } = require('./message');
describe("funcs", () => {
it("buildText", async () => {
const mock = jest.spyOn(Message, 'findOne'); // spy on Message.findOne()
mock.mockImplementation(() => Promise.resolve({
message: 'the message'
})); // replace the implementation
let listing = {
_id: "1324",
pricingEnabled: true,
listingFound: true,
hideListing: null
};
let messageRule = {
_id: "3452345",
minNights: 1,
reviewEnabled: false,
disableMessageAfterReview: false,
message: 'test',
lastMinuteMessage: 'test2'
};
let reservation = {
_id: "63452345",
hasLeftReview: true,
hasIssues: false
};
let isReview = false;
let isLastMinuteMessage = false;
let response = await Code.buildText(listing, messageRule, reservation, isReview, isLastMinuteMessage);
expect(response).toMatchSnapshot();
mock.mockRestore(); // restore Message.findOne()
});
});
message.js(示例的虚拟模型)
const mongoose = require('mongoose');
exports.Message = mongoose.model('Message', new mongoose.Schema({ }));
答案 1 :(得分:0)
我对buildText并不是100%的确定(尽管我从未使用过new Promise(async ...)
,但对我来说看起来不错)-因此,我将重点放在测试上:据我所知,您正在做基本的事情。唯一的事情是您没有
// jest.mock('mongoose'); doesn't work, unfortunately
const mReal = require('mongoose');
const mMock = mReal;
然后添加一个beforeAll
之类的
beforeAll(() => { // not 110% clean, but I'm not alone: https://github.com/facebook/jest/issues/936#issuecomment-214556122
mMock.model = jest.fn(); // manually overwrite one fct with a mock
});
在code.test.js
的第一行;加号:您需要先训练模拟,然后在开始时it
插入
it("...", () => {
const findOneMock = jest.fn();
findOneMock.mockReturnValue(Promise.resolve({message: "hey"}));
mMock.model.mockReturnValue({findOne: findOneMock});
// prep done, test something
我使用了一些简单的测试代码,我想您的代码将等效:
let res = await mMock.model('whatever').findOne('whatever');
expect(res.message).toBe("hey");
});
希望我对所有隐藏的细节(例如您对Message
的看法)正确无误-但是,现在,您应该真正解决某些问题。
答案 2 :(得分:0)
如果使用的是开玩笑,那么最好的方法是定义一个名为setup.js的文件,该文件将在运行任何测试文件之前运行,然后在该文件中,导入猫鼬模型,然后建立连接您的测试数据库。 (这是因为您的测试文件与服务器文件是分开运行的,并且对猫鼬模型或数据库连接一无所知,因此,通过定义此文件并建立连接,您可以为测试环境定义猫鼬,并且可以将其用作您想要的而不是null)
您需要完成三个步骤:
首先在package.json中运行,以告诉jest在运行任何其他测试文件之前先运行文件的内容,您需要在脚本块之前添加此块:
"jest": {
"setupTestFrameworkScriptFile": "./tests/setup.js"
}
然后,您需要在模型中使用mongoose和setup.js文件中的mongoose库进行需求,然后建立与数据库的连接:
require('../models/yourModel'); //require in any models that you need to use in your tests
const mongoose = require('mongoose');
mongoose.connect(mongoURI,{useMongoClient: true});
mongoose.connection.once('open',()=>{}).on('error',(err)=>
{console.log(err)});
然后,您可以在测试文件中使用模型来运行或测试猫鼬的任何查询,例如,如果要在测试文件中创建名为Model的模型的记录,则:
const mongoose = require('mongoose');
const Model = mongoose.model('Model');
const newRecord = await new Model({}).save();
//test newRecord