我如何用笑话测试议程工作?

How do I test an agenda job with jest?

我想测试我在 运行 议程中的工作。我已经编写了以下测试,但后来我意识到在确定测试通过或失败之前,所有 expect()... 函数都没有被调用。我在所有 expect() 函数中放置了一些 console.log() 并且它们在确定测试结果之前确实被调用了。我尝试在测试的顶部添加 expect.assertions(6); 但它并没有使测试等待更长时间,它只是失败说它没有找到所有 6.

如何让 jest 等待整个测试完成?

这是我要测试的代码:

rules.js

const Account = require("./../models/user.account");
const Listing = require("./../models/user.account.listing");
const Message = require("./../models/user.account.listing.message");
const MessageRule = require("./../models/user.account.listing.messageRule");
const Reservation = require("./../models/user.account.listing.reservation");
const Core = require("./../core");
const moment = require("moment-timezone");
require("colors");

module.exports = function(agenda) {
    agenda.define("send message", {priority: "highest"}, async (job, done) => {
        try {
            console.time("send message " + job.attrs._id);
            const userID = job.attrs.data.userID;
            const listingID = job.attrs.data.listingID;
            const reservationID = job.attrs.data.reservationID;
            const messageRuleID = job.attrs.data.messageRuleID;
            const sendDate = job.attrs.data.sendDate;

            //console.log("Rule Job:".cyan + " send message - listingID: " + listingID);
            let messageQuery = {
                userID,
                listingID,
                reservationID,
                messageRuleID
            };
            let message = await Message.findOne(messageQuery);
            if (message) {
                throw new Error(
                    "Message has already been sent. userID: " +
                        userID +
                        " listingID: " +
                        listingID +
                        " reservationID: " +
                        reservationID +
                        " messageRuleID: " +
                        messageRuleID +
                        " message._id: " +
                        message._id +
                        " message.sendDate: " +
                        message.sendDate +
                        " message.sentDate: " +
                        message.sentDate
                );
            } else {
                const isLastMinuteMessage = false;
                let listing = await Listing.findById(listingID);
                let account = await Account.findById(listing.accountID);
                let messageRule = await MessageRule.findById(messageRuleID);
                let reservation = await Reservation.findById(reservationID);
                // Check that it found all of the required documents
                if (!listing || !listing._id) {
                    throw new Error("Missing the listing document. userID: " + userID + " listingID: " + listingID);
                }
                if (!account || !account._id) {
                    throw new Error(
                        "Missing the account document. userID: " + userID + " accountID: " + listing.accountID
                    );
                }
                if (!messageRule || !messageRule._id) {
                    throw new Error(
                        "Missing the messageRule document. userID: " + userID + " messageRuleID: " + messageRuleID
                    );
                }
                if (!reservation || !reservation._id) {
                    throw new Error(
                        "Missing the reservation document. userID: " + userID + " reservationID: " + reservationID
                    );
                }
                // Double check the send date by recalculating it then checking comparing them
                if (messageRule.event == "checkin" || messageRule.event == "checkout") {
                    let sendDateCheck = moment.tz(
                        reservation.startDate + " " + messageRule.time,
                        "YYYY-MM-DD H",
                        listing.timeZone
                    );
                    if (messageRule.event == "checkout") {
                        sendDateCheck = sendDateCheck.add(reservation.nights, "day");
                    }
                    sendDateCheck = sendDateCheck.add(messageRule.days, "day");
                    if (!sendDateCheck.isSame(sendDate)) {
                        throw new Error(
                            "Message send date and calculated send date don't match. userID: " +
                                userID +
                                " listingID: " +
                                listingID +
                                " reservationID: " +
                                reservationID +
                                " messageRuleID: " +
                                messageRuleID +
                                " sendDate: " +
                                moment(sendDate).format() +
                                " sendDateCheck: " +
                                moment(sendDateCheck).format()
                        );
                    }
                }
                await Core.buildMessage(account, listing, messageRule, reservation, isLastMinuteMessage);
            }
            console.timeEnd("send message " + job.attrs._id);
            done();
        } catch (error) {
            console.error("Rule Job: send message", error);
            return done(error);
        }
    });
};

这是我的测试:

rules.test.js

const Account = require("./../models/user.account");
const Listing = require("./../models/user.account.listing");
const Message = require("./../models/user.account.listing.message");
const MessageRule = require("./../models/user.account.listing.messageRule");
const Reservation = require("./../models/user.account.listing.reservation");
const Core = require("./../core");
const Rules = require("./rules");
const Docs = require("./../tests/docs");

describe("Tests for rules.js", () => {
    // Mock moment()
    Date.now = jest.fn(() => 1538794832371); //October 5th 2018 8pm PST

    beforeEach(() => {
        jest.clearAllMocks();
    });

    describe("rules()", () => {
        it("should send a message, message exists but is enabled", async () => {
            // Mock Message
            // Message.findOne()
            const MessageFindOneMock = jest.spyOn(Message, "findOne");
            const MessageFindOneResult = Docs.messageReviewReminderDisabledThenEnabled;
            const MessageFindOne = jest.fn(() => MessageFindOneResult);
            MessageFindOneMock.mockImplementation(MessageFindOne);

            const userID = Docs.userID;
            const reservation = Docs.reservationInTheFuture;
            const messageRule = Docs.messageRuleCheckUp;
            const accountID = Docs.listing.accountID;
            const listingID = Docs.listing._id;
            const reservationID = reservation._id;
            const messageRuleID = messageRule._id;

            // Mock Listing
            // Listing.findById()
            const ListingFindByIdMock = jest.spyOn(Listing, "findById");
            const ListingFindByIdResult = Docs.listing;
            const ListingFindById = jest.fn(() => ListingFindByIdResult);
            ListingFindByIdMock.mockImplementation(ListingFindById);
            // Mock Account
            // Account.findById()
            const AccountFindByIdMock = jest.spyOn(Account, "findById");
            const AccountFindByIdResult = {_id: accountID};
            const AccountFindById = jest.fn(() => AccountFindByIdResult);
            AccountFindByIdMock.mockImplementation(AccountFindById);
            // Mock MessageRule
            // MessageRule.findById()
            const MessageRuleFindByIdMock = jest.spyOn(MessageRule, "findById");
            const MessageRuleFindByIdResult = messageRule;
            const MessageRuleFindById = jest.fn(() => MessageRuleFindByIdResult);
            MessageRuleFindByIdMock.mockImplementation(MessageRuleFindById);
            // Mock Reservation
            // Reservation.findById()
            const ReservationFindByIdMock = jest.spyOn(Reservation, "findById");
            const ReservationFindByIdResult = reservation;
            const ReservationFindById = jest.fn(() => ReservationFindByIdResult);
            ReservationFindByIdMock.mockImplementation(ReservationFindById);
            // Mock Core
            // Core.buildMessage()
            const CoreBuildMessageMock = jest.spyOn(Core, "buildMessage");
            const CoreBuildMessage = jest.fn((account, listing, messageRule, reservation, isLastMinuteMessage) => {
                expect(account._id).toBe(accountID);
                expect(listing._id).toBe(listingID);
                expect(messageRule._id).toBe(messageRuleID);
                expect(reservation._id).toBe(reservationID);
            });
            CoreBuildMessageMock.mockImplementation(CoreBuildMessage);
            // Run test
            const sendDate = "2018-11-08T10:00:00-06:00";
            const done = jest.fn(error => {
                expect(error).toBeFalsy();
                expect(CoreBuildMessage).toHaveBeenCalledTimes(10);
            });
            const job = {
                attrs: {
                    data: {
                        userID,
                        listingID,
                        reservationID,
                        messageRuleID,
                        sendDate
                    }
                }
            };
            let agenda = {
                define: jest.fn((name, options, callback) => {
                    if (name == "send message") {
                        callback(job, done);
                    }
                })
            };
            Rules(agenda);
        });
    });
});

在您的 rules.js 中,您已将 callback 定义为 async 函数:

agenda.define("send message", {priority: "highest"}, async (job, done) // <--- this

无论您如何调用它:

define: jest.fn((name, options, callback) => {
    if (name == "send message") {
        callback(job, done);
    }
})

所以那里没有 await ...

这就解释了为什么你得到东西 运行 而不是 awaiting 才能完成。

应该是这样的:

define: await jest.fn((name, options, callback) => {
    if (name == "send message") {
        await callback(job, done);
    }
})