使用 Jest 測試框架調用 fetch(url) 時如何根據 url 模擬變量響應? (How to mock variable responses based on the url when fetch(url) is called using the Jest testing framework?)


問題描述

使用 Jest 測試框架調用 fetch(url) 時如何根據 url 模擬變量響應? (How to mock variable responses based on the url when fetch(url) is called using the Jest testing framework?)

我有一個如下所示的模塊:

calculate‑average.js

const fetch = require('node‑fetch')
const stats = require('stats‑lite')
const BASE_URL = 'https://www.example.com/api'

const calculateAverage = async(numApiCalls) => {
  const importantData = []

  for (let i = 0; i < numApiCalls; i++) {
      const url = `${BASE_URL}/${i}` // will make requests to https://www.example.com/api/0, https://www.example.com/api/1 and so on....
      const res = await fetch(url)
      const jsonRes = await res.json()

      importantData.push(jsonRes.importantData)
  }

  return stats.mean(importantData)
}

module.exports = calculateAverage

我試過測試它按照以下思路,但我顯然遠離解決方案:

calculate‑average.test.js

const calculateAverage = require('../calculate‑average')

jest.mock(
    'node‑fetch',
    () => {
        return jest.fn(() => {})
    }
)

test('Should calculate stats for liquidation open interest delatas', async() => {
    const stats = await calculateAverage(100) // Should make 100 API calls.

    console.log(stats)
})

我需要做的是:

  1. 能夠為每個 API 調用指定自定義的變化響應。例如,我應該能夠指定對 https://www.example.com/api/0 的調用返回 {importantData: 0 },對https://www.example.com/api/1 返回 { importantData: 1 } 以此類推...
  2. 如果向我未指定響應的url 發出請求,則會提供默認響應。例如,如果對 https://www.example.com/api/101 做出響應,則發送默認響應 {importantData: 1000 }

我希望只使用 Jest 而不依賴於像 mock‑fetchjest‑mock‑fetch 這樣的模塊。但是,如果不使用的解決方案過於復雜,那麼我很樂意使用它們。只是不想在不需要時創建不必要的依賴項。

提供默認響應。例如,如果對 https://www.example.com/api/101 做出響應,則發送默認響應 {importantData: 1000 }

我希望只使用 Jest 而不依賴於像 mock‑fetchjest‑mock‑fetch 這樣的模塊。但是,如果不使用的解決方案過於復雜,那麼我很樂意使用它們。只是不想在不需要時創建不必要的依賴項。

提供默認響應。例如,如果對 https://www.example.com/api/101 做出響應,則發送默認響應 {importantData: 1000 }

我希望只使用 Jest 而不依賴於像 mock‑fetchjest‑mock‑fetch 這樣的模塊。但是,如果不使用的解決方案過於復雜,那麼我很樂意使用它們。只是不想在不需要時創建不必要的依賴項。

我最好只使用 Jest 而不依賴於 mock‑fetchjest‑mock‑fetch 等模塊來執行此操作。但是,如果不使用的解決方案過於復雜,那麼我很樂意使用它們。只是不想在不需要時創建不必要的依賴項。

我最好只使用 Jest 而不依賴於 mock‑fetchjest‑mock‑fetch 等模塊來執行此操作。但是,如果不使用的解決方案過於復雜,那麼我很樂意使用它們。只是不想在不需要時創建不必要的依賴項。


參考解法

方法 1:

Sure you can! You can use mock function mockResolvedValueOnce method to return a result for a specific call and mockResolvedValue to return the default result.

jest.mock('node‑fetch', () => {
    const generateResponse = (value) => {
        return { json: () => ({ importantData: value }) };
    };

    return jest
        .fn()
        .mockResolvedValue(generateResponse(1000)) // default response
        .mockResolvedValueOnce(generateResponse(0)) // response for first call
        .mockResolvedValueOnce(generateResponse(1)) // response for second call
        .mockResolvedValueOnce(generateResponse(2)); // response for third call
});

Note that we are returning an object with the json property so that it returns the json data when you call res.json() in calculate‑average.js.


If you want to return a specific response based on the url parameter, you will have to mock the desired behaviour in the returned mock function for node‑fetch. The following example will mock the returned value so that for URLs where the counter is greater than 100 it will return 1000. Otherwise, it will return the same value present in the url:

jest.mock('node‑fetch', () => {
    return jest.fn((url) => {
        // Get and parse the URL parameter.
        const value = parseInt(url.split('/').slice(‑1)[0], 10);

        return Promise.resolve({
            json: () => ({ importantData: value > 100 ? 1000 : value })
        });
    });
});

(by philosophermgarcia)

參考文件

  1. How to mock variable responses based on the url when fetch(url) is called using the Jest testing framework? (CC BY‑SA 2.5/3.0/4.0)

#fetch #jestjs #node.js #unit-testing #mocking






相關問題

mysql fetch 中的 $row 是什麼類型的變量? (What kind of variable is $row from a mysql fetch?)

如何在 PHP 中使用 bind_params 正確獲取數據到數組 (How to correctly fetch data to array with bind_params in PHP)

使用 JavaMail 加速電子郵件檢索 (Speed up email retrieval with JavaMail)

使用 eclipselink 從多個表中獲取數據 (Fetch data from multiple tables using eclipselink)

如何在 Webassembly 中獲取 JSON 文件 (How to Fetch a JSON file in Webassembly)

mysqli(a,b,c,d)->query(sql)->fetch_assoc() 究竟是如何工作的? (How exactly does mysqli(a,b,c,d)->query(sql)->fetch_assoc() work?)

如何在 .map 中返回異步函數? (How do I make an asynchronous function return in .map?)

如何僅在響應中的 onclick 事件後映射 json 列表? (How to map a json list only after an onclick event in react?)

在第二個 API 中使用來自第一個 API 的信息 - React (Using information from the first API in the second one - React)

使用 Jest 測試框架調用 fetch(url) 時如何根據 url 模擬變量響應? (How to mock variable responses based on the url when fetch(url) is called using the Jest testing framework?)

函數不返回對像以供 .then 使用 - 但能夠 console.log 對象,並明確返回它 (Function not returning object for .then to work with - but able to console.log the object, and am explicitly returning it)

fetch api - 400 加載資源失敗 (fetch api - 400 failed to load resource)







留言討論