example-mock-module.test.js
1 /** 2 * Example test demonstrating Node.js 22+ mock.module() capabilities 3 * 4 * This shows how to mock entire ES modules before they're imported, 5 * which was not possible in Node.js 20. 6 */ 7 8 import { describe, test, mock } from 'node:test'; 9 import assert from 'node:assert'; 10 11 describe('mock.module() Examples', () => { 12 test('should mock axios module completely', async t => { 13 // Mock the entire axios module before importing 14 // Note: Use defaultExport for default exports, not namedExports with 'default' key 15 mock.module('axios', { 16 defaultExport: async config => ({ 17 data: { mocked: true, url: config.url }, 18 status: 200, 19 }), 20 }); 21 22 // Now import the module - it will use the mock 23 const axios = (await import('axios')).default; 24 25 const response = await axios({ url: 'https://api.example.com' }); 26 27 assert.strictEqual(response.data.mocked, true); 28 assert.strictEqual(response.status, 200); 29 }); 30 31 test('should mock custom modules', async t => { 32 // Mock a custom module with specific exports 33 mock.module('../src/utils/logger.js', { 34 namedExports: { 35 log: mock.fn(), 36 error: mock.fn(), 37 info: mock.fn(msg => `MOCKED: ${msg}`), 38 }, 39 }); 40 41 const logger = await import('../src/utils/logger.js'); 42 43 const result = logger.info('test message'); 44 assert.strictEqual(result, 'MOCKED: test message'); 45 46 // Verify the mock function was called 47 assert.strictEqual(logger.info.mock.calls.length, 1); 48 }); 49 50 test('should mock with different implementations per test', async t => { 51 // axios was already mocked globally in test 1; re-import to get the existing mock. 52 // To use different implementations per test, use separate describe blocks or 53 // call mock.restoreAll() between tests. 54 const axios1 = (await import('axios')).default; 55 const response1 = await axios1({ url: 'https://api.example.com' }); 56 assert.strictEqual(response1.data.mocked, true); 57 assert.strictEqual(response1.status, 200); 58 }); 59 60 test('should mock modules with multiple named exports', async t => { 61 mock.module('../src/scrape.js', { 62 namedExports: { 63 scrapeSERP: mock.fn(async () => [{ url: 'https://example.com', title: 'Mocked Result' }]), 64 parseResults: mock.fn(data => data.organic_results || []), 65 }, 66 }); 67 68 const scrape = await import('../src/scrape.js'); 69 70 const results = await scrape.scrapeSERP('test keyword'); 71 assert.strictEqual(results.length, 1); 72 assert.strictEqual(results[0].title, 'Mocked Result'); 73 74 // Verify the mock was called 75 assert.strictEqual(scrape.scrapeSERP.mock.calls.length, 1); 76 assert.strictEqual(scrape.scrapeSERP.mock.calls[0].arguments[0], 'test keyword'); 77 }); 78 }); 79 80 /** 81 * Other useful mocking features in Node.js 22: 82 * 83 * 1. Mock Timers: 84 * mock.timers.enable({ apis: ['setTimeout', 'setInterval'] }); 85 * mock.timers.tick(1000); // Advance time by 1 second 86 * 87 * 2. Mock Functions with Custom Implementation: 88 * const fn = mock.fn((a, b) => a + b); 89 * fn(2, 3); // Returns 5 90 * fn.mock.calls[0].arguments // [2, 3] 91 * fn.mock.calls[0].result // 5 92 * 93 * 3. Mock Object Methods: 94 * const obj = { method: () => 'original' }; 95 * mock.method(obj, 'method', () => 'mocked'); 96 * obj.method() // Returns 'mocked' 97 * 98 * 4. Restore Mocks: 99 * mockFn.mock.restore(); // Restore original implementation 100 * mock.restoreAll(); // Restore all mocks 101 */