Как издеваться над примитивным значением const с помощью jest и восстановить макет?

#javascript #jestjs #mocking

#javascript #jestjs #издевательство

Вопрос:

Итак, предположим, у меня есть файл с именем «config.js «:

 export const DELAY_SECONDS = 5;
  

И при выполнении тестов:

 // Ignore the delay when doing the tests.
jest.mock("/path/to/config", () => ({ DELAY_SECONDS: 0 }))
  

Но я также хочу проверить, работает ли исходное значение:

 it('should work with delay', () => {
    // Use original value implicitly.
    a_function_uses_DELAY_SECONDS()
    expect(...).toBe(...)
})
  

Как я могу восстановить этот макет? Или есть лучший способ реализовать макет?

Я пробовал что-то ниже, и ни один из них не работает:

 it('should work with delay', () => {
    jest.unmock() // Doesn't work at all, don't even know what does this method do.
    // Use original value implicitly.
    a_function_uses_DELAY_SECONDS()
    expect(...).toBe(...)
})
  
 it('should work with delay', () => {
    jest.mock("/path/to/config", () => ({ DELAY_SECONDS: 5 })) // Call the mock again doesn't work
    // Use original value implicitly.
    a_function_uses_DELAY_SECONDS()
    expect(...).toBe(...)
})
  
 it('should work with delay', () => {
    const config = require("/path/to/config").default;
    config.DELAY_SECONDS = 5; // Won't work, as it is a constant, cannot modify
    // Use original value implicitly.
    a_function_uses_DELAY_SECONDS()
    expect(...).toBe(...)
})
  

Ответ №1:

Вы могли бы использовать jest.doMock(moduleName, factory, options).

Например.

config.js :

 export const DELAY_SECONDS = 5;
  

main.js :

 import { DELAY_SECONDS } from './config';

function main() {
  return DELAY_SECONDS;
}

export { main };
  

main.test.js :

 describe('64473533', () => {
  beforeEach(() => {
    jest.resetModules();
  });
  it('should work with delay - original', () => {
    const { main } = require('./main');
    const actual = main();
    expect(actual).toBe(5);
  });
  it('should work with delay - mocked', () => {
    jest.doMock('./config', () => ({ DELAY_SECONDS: 0 }));
    const { main } = require('./main');
    const actual = main();
    expect(actual).toBe(0);
  });
});
  

результат модульного теста:

  PASS  src/stackoverflow/64473533/main.test.js
  64473533
    ✓ should work with delay - original (445ms)
    ✓ should work with delay - mocked (2ms)

-----------|----------|----------|----------|----------|-------------------|
File       |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
-----------|----------|----------|----------|----------|-------------------|
All files  |      100 |      100 |      100 |      100 |                   |
 config.js |      100 |      100 |      100 |      100 |                   |
 main.js   |      100 |      100 |      100 |      100 |                   |
-----------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests:       2 passed, 2 total
Snapshots:   0 total
Time:        3.694s
  

Комментарии:

1. Спасибо, выглядит отлично. Есть ли способ отменить этот прогресс? О, я понял. Я могу doMock в том beforeEach и только resetModules в том тесте, который я хочу, верно?

2. @Sraw Лучше издеваться в зависимости от необходимости, как следует из ответа. И выполнение resetModules не каждый раз может сделать тесты непредсказуемыми. Если вам нужно сохранить доступ к исходной реализации, на которую не повлияет doMock, импортируйте ее на верхнем уровне.