99re热这里只有精品视频,7777色鬼xxxx欧美色妇,国产成人精品一区二三区在线观看,内射爽无广熟女亚洲,精品人妻av一区二区三区

Jest 手動模擬

2021-09-18 20:25 更新

手動模擬用于通過模擬數(shù)據(jù)來剔除功能。例如,你可能希望創(chuàng)建一個允許使用假數(shù)據(jù)的手動模擬,而不是訪問像網(wǎng)站或數(shù)據(jù)庫這樣的遠(yuǎn)程資源。這將確保你的測試速度快,而且不會出現(xiàn)問題。

模擬用戶模塊

手動模擬是通過在?__mocks__/?緊鄰模塊的子目錄中編寫模塊來定義的。例如,mock 一個名為模塊?user?的?models?目錄下,創(chuàng)建一個名為?user.js?,并把它的?models/__mocks__?目錄中。請注意,?__mocks__?文件夾區(qū)分大小寫,因此命名目錄?__MOCKS__?在某些系統(tǒng)上會中斷。

當(dāng)我們需要在我們的測試,模塊,顯式調(diào)用?jest.mock('./moduleName')?是必需的。

模擬節(jié)點模塊

如果lodash?模擬的模塊是 Node 模塊(例如:),則模擬應(yīng)放置在?__mocks__?相鄰的目錄中?node_modules?(除非你配置roots為指向項目根目錄以外的文件夾),并且會自動模擬。無需顯式調(diào)用?jest.mock('module_name')?.

可以通過在與作用域模塊名稱匹配的目錄結(jié)構(gòu)中創(chuàng)建文件來模擬作用域模塊。例如,要模擬名為@scope/project-name?的作用域模塊?,請在__mocks__/@scope/project-name.js?處創(chuàng)建一個文件?,并相應(yīng)地創(chuàng)建?@scope/?目錄。

提示:如果我們想模擬節(jié)點的核心模塊(例如:?fs?或?path?),則顯式調(diào)用例如?jest.mock('path')?是需要的,因為核心節(jié)點模塊默認(rèn)情況下不會被模擬。

例子

  1. .
  2. ├── config
  3. ├── __mocks__
  4. │ └── fs.js
  5. ├── models
  6. │ ├── __mocks__
  7. │ │ └── user.js
  8. │ └── user.js
  9. ├── node_modules
  10. └── views

當(dāng)給定模塊存在手動模擬時,Jest 的模塊系統(tǒng)將在顯式調(diào)用?jest.mock('moduleName')?時使用該模塊. 但是,當(dāng)?automock?設(shè)置為時?true?,即使?jest.mock('moduleName')?沒有調(diào)用,也會使用手動模擬實現(xiàn)而不是自動創(chuàng)建的模擬。要選擇退出此行為,需要顯式調(diào)用?jest.unmock('moduleName')?應(yīng)使用實際模塊實現(xiàn)的測試。

注意:為了正確模擬,Jest 需要?jest.mock('moduleName')?與?require/import?語句在同一范圍內(nèi)。

這是一個人為的示例,其中我們有一個模塊,該模塊提供給定目錄中所有文件的摘要。在這種情況下,我們使用核心(內(nèi)置)?fs?模塊。

  1. // FileSummarizer.js
  2. 'use strict';
  3. const fs = require('fs');
  4. function summarizeFilesInDirectorySync(directory) {
  5. return fs.readdirSync(directory).map(fileName => ({
  6. directory,
  7. fileName,
  8. }));
  9. }
  10. exports.summarizeFilesInDirectorySync = summarizeFilesInDirectorySync;

由于我們希望我們的測試避免實際訪問磁盤(這非常緩慢和脆弱),我們fs通過擴展自動模擬為模塊創(chuàng)建了一個手動模擬。我們的手動模擬將實現(xiàn)?fs?我們可以為測試構(gòu)建的API 的自定義版本:

  1. // __mocks__/fs.js
  2. 'use strict';
  3. const path = require('path');
  4. const fs = jest.createMockFromModule('fs');
  5. // This is a custom function that our tests can use during setup to specify
  6. // what the files on the "mock" filesystem should look like when any of the
  7. // `fs` APIs are used.
  8. let mockFiles = Object.create(null);
  9. function __setMockFiles(newMockFiles) {
  10. mockFiles = Object.create(null);
  11. for (const file in newMockFiles) {
  12. const dir = path.dirname(file);
  13. if (!mockFiles[dir]) {
  14. mockFiles[dir] = [];
  15. }
  16. mockFiles[dir].push(path.basename(file));
  17. }
  18. }
  19. // A custom version of `readdirSync` that reads from the special mocked out
  20. // file list set via __setMockFiles
  21. function readdirSync(directoryPath) {
  22. return mockFiles[directoryPath] || [];
  23. }
  24. fs.__setMockFiles = __setMockFiles;
  25. fs.readdirSync = readdirSync;
  26. module.exports = fs;

現(xiàn)在我們編寫我們的測試。請注意,我們需要明確說明我們要模擬該?fs?模塊,因為它是一個核心 Node 模塊:

  1. // __tests__/FileSummarizer-test.js
  2. 'use strict';
  3. jest.mock('fs');
  4. describe('listFilesInDirectorySync', () => {
  5. const MOCK_FILE_INFO = {
  6. '/path/to/file1.js': 'console.log("file1 contents");',
  7. '/path/to/file2.txt': 'file2 contents',
  8. };
  9. beforeEach(() => {
  10. // Set up some mocked out file info before each test
  11. require('fs').__setMockFiles(MOCK_FILE_INFO);
  12. });
  13. test('includes all files in the directory in the summary', () => {
  14. const FileSummarizer = require('../FileSummarizer');
  15. const fileSummary = FileSummarizer.summarizeFilesInDirectorySync(
  16. '/path/to',
  17. );
  18. expect(fileSummary.length).toBe(2);
  19. });
  20. });

此處顯示的示例模擬jest.createMockFromModule用于生成自動模擬,并覆蓋其默認(rèn)行為。這是推薦的方法,但完全是可選的。如果你根本不想使用自動模擬,可以從模擬文件中導(dǎo)出自己的函數(shù)。完全手動模擬的一個缺點是它們是手動的——這意味著你必須在它們模擬的模塊發(fā)生變化時手動更新它們。因此,最好在滿足你的需要時使用或擴展自動模擬。

為確保手動模擬及其實際實現(xiàn)保持同步,要求jest.requireActual(moduleName)在手動模擬中使用真實模塊并在導(dǎo)出之前使用模擬函數(shù)對其進(jìn)行修改可能很有用。

此示例的代碼可在examples/manual-mocks 中找到。

與 ES 模塊導(dǎo)入一起使用

如果你使用ES 模塊導(dǎo)入,那么你通常會傾向于將你的?import?語句放在測試文件的頂部。但通常你需要在模塊使用之前指示 Jest 使用模擬。出于這個原因,Jest 會自動將?jest.mock?調(diào)用提升到模塊的頂部(在任何導(dǎo)入之前)。要了解有關(guān)此內(nèi)容的更多信息并查看其實際效果,請參閱此內(nèi)容

未在 JSDOM 中實現(xiàn)的模擬方法

如果某些代碼使用了 JSDOM(Jest 使用的 DOM 實現(xiàn))尚未實現(xiàn)的方法,則很難對其進(jìn)行測試。這是例如與window.matchMedia()?的情況?。Jest 返回?TypeError: window.matchMedia is not a function?并且沒有正確執(zhí)行測試。

在這種情況下,?matchMedia?在測試文件中進(jìn)行模擬應(yīng)該可以解決問題:

  1. Object.defineProperty(window, 'matchMedia', {
  2. writable: true,
  3. value: jest.fn().mockImplementation(query => ({
  4. matches: false,
  5. media: query,
  6. onchange: null,
  7. addListener: jest.fn(), // deprecated
  8. removeListener: jest.fn(), // deprecated
  9. addEventListener: jest.fn(),
  10. removeEventListener: jest.fn(),
  11. dispatchEvent: jest.fn(),
  12. })),
  13. });

如果?window.matchMedia()?在測試中調(diào)用的函數(shù)(或方法)中使用,則此方法有效。如果?window.matchMedia()?直接在測試文件中執(zhí)行,Jest 也會報同樣的錯誤。在這種情況下,解決方案是將手動模擬移動到一個單獨的文件中,并在測試文件之前將其包含在測試中:

  1. import './matchMedia.mock'; // Must be imported before the tested file
  2. import {myMethod} from './file-to-test';
  3. describe('myMethod()', () => {
  4. // Test the method here...
  5. });


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號