簡體   English   中英

在另一個模塊中使用的 Jest 模擬模塊函數

[英]Jest mock module functions used in another module

我是 Jest 的新手,正在嘗試對一些現有代碼編寫一些測試。 雖然我在一個模塊(例如this )中看到過很多關於 mocking 函數的 Jest 文章和 Stackoverflow 帖子,但我相信我正在嘗試完成一些有點高級或非常愚蠢並且需要代碼重構的東西。 無論哪種方式,我都不確定,非常感謝您的幫助!

讓我用一個示例代碼來解釋我的情況。 假設我們正在處理一個電子商務系統,並且后端有一個模塊可以從某個 API 中獲取訂單詳細信息:

// get-order-data.js

const getOrderDataFromApi = async (orderId) => {
    // . . . some API call
    console.log("The actual getOrderData function called!");
}

// Added only to emphasize that the entire module shouldn't be mocked
const getOrderDataFromDatabase = async (orderId) => { }

module.exports = {
    getOrderDataFromApi,
    getOrderDataFromDatabase,
}

然后有一個非常相似的模塊用於獲取訂單的交付數據:

// get-delivery-data.js

const getDeliveryDataFromApi = async (orderId) => {
    // . . . some API call
    console.log("The actual getDeliveryDataFromApi function called!");
}

// Added only to emphasize that the entire module shouldn't be mocked
const getDeliveryDataFromDatabase = async (orderId) => { }

module.exports = {
    getDeliveryDataFromApi,
    getDeliveryDataFromDatabase,
}

如您所見,每個模塊中都有一個console.log ,用於指示已執行原始代碼而不是模擬代碼。

現在,假設這兩個模塊都被另一個模塊 function 使用,如下所示:

// combine-order-data.js
const { getDeliveryDataFromApi } = require("./get-delivery-data");
const { getOrderDataFromApi } = require("./get-order-data")

const combineOrderData = async (orderId) => {
    const orderData = await getOrderDataFromApi(orderId);
    const deliveryData = await getDeliveryDataFromApi(orderId);

    return {
        orderData,
        deliveryData,
    };
}

module.exports = {
    combineOrderData,
};

我想通過 mocking out getOrderDataFromApi()getDeliveryDataFromApi()來測試這個combineOrderData() function 的行為。

為此,我創建了以下測試文件:

// order.test.js

const { combineOrderData } = require("./combine-order-data");

const mockedOrderData = {
    id: 1,
    amount: 1000,
};

const mockedDelieryData = {
    orderId: 1,
    status: 'DELIVERED',
};

beforeEach(() => {
    jest.mock("./get-order-data", () => {
        getOrderDataFromApi: jest.fn(() => Promise.resolve(mockedOrderData))
    });
    jest.mock("./get-delivery-data", () => {
        getDeliveryDataFromApi: jest.fn(() => Promise.resolve(mockedDelieryData))
    });
});

test("combineOrderData correctly combines data", async () => {
    const combinedOrder = await combineOrderData(111);
});

當我現在運行 npx npx jest時,我看到 output 中的console.log s,告訴我 mocking 沒有成功:

  console.log
    The actual getOrderData function called!

      at getOrderDataFromApi (get-order-data.js:3:13)

  console.log
    The actual getDeliveryDataFromApi function called!

      at getDeliveryDataFromApi (get-delivery-data.js:3:13)

 PASS  ./order.test.js
  ✓ combineOrderData correctly combines data (28 ms)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        0.227 s
Ran all test suites related to changed files.

我認為這是因為當combineOrderData()被調用時,它實例化了它自己的所用模塊的副本(我認為默認情況下 Node 模塊是單例的;因為只有一個導入模塊的副本存在並且由所有require s 共享) ?

無論如何,我不知道實現這一目標的正確方法是什么。

另外,如果代碼結構被破壞並且重構可以解決問題,請隨時發表評論,但我不知道如何避免編寫和測試進行其他 function 調用的代碼,所以我似乎會遇到這個問題經常。

我在測試中發現了 2 個問題

  1. 使用 jest.mock 時,應在回調中返回 object,在您的情況下缺少括號
jest.mock("./get-delivery-data", () => ({
  getDeliveryDataFromApi: jest.fn(() => Promise.resolve(mockedDelieryData)),
}));
  1. mocking 導入順序錯誤。

首先require導入實際模塊而不是模擬模塊。

工作測試

jest.mock("./get-order-data", () => ({
  getOrderDataFromApi: jest.fn(() => Promise.resolve(mockedOrderData)),
}));
jest.mock("./get-delivery-data", () => ({
  getDeliveryDataFromApi: jest.fn(() => Promise.resolve(mockedDelieryData)),
}));
const { combineOrderData } = require("./combine-order-data");

const mockedOrderData = {
  id: 1,
  amount: 1000,
};

const mockedDelieryData = {
  orderId: 1,
  status: "DELIVERED",
};

test("combineOrderData correctly combines data", async () => {
  const combinedOrder = await combineOrderData(111);
});

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM