javascript - Hur ändrar man beteendet hos en mockad import i Jest?


Jag har problem med att ändra beteendet hos en mockad modul i Jest. Jag vill mocka olika beteenden för att testa hur min kod kommer att agera under dessa olika omständigheter. Jag vet inte hur jag ska göra detta eftersom anrop till jest.mock() flyttas upp till toppen av filen, så jag kan inte bara anropa jest.mock() för varje test. Finns det ett sätt att ändra beteendet hos en mockad modul för ett enskilt test?

jest.mock('the-package-to-mock', () => ({
    methodToMock: jest.fn(() => console.log('Hello'))
}))

import * as theThingToTest from './toTest'
import * as types from './types'

it('Test A', () => {
    expect(theThingToTest.someAction().type).toBe(types.SOME_TYPE)
})

it('Test B', () => {
    // I need the-package-to-mock.methodToMock to behave differently here
    expect(theThingToTest.someAction().type).toBe(types.OTHER_TYPE)
})

Internt, som du kan föreställa dig, importerar och använder theThingToTest.someAction() the-package-to-mock.methodToMock().

Svar #1

Efter att du har gjort en mock av modulen och ersatt methodToMock med en spion, behöver du importera den. Sedan, vid varje test, kan du ändra beteendet hos methodToMock genom att anropa spionmetoden mockImplementation.

jest.mock('the-package-to-mock', () => ({
    methodToMock: jest.fn()
}))

import { methodToMock } from 'the-package-to-mock'

it('Test A', () => {
    methodToMock.mockImplementation(() => 'Value A')
    // Test your function that uses the mocked package's function here.
})

it('Test B', () => {
    methodToMock.mockImplementation(() => 'Value B')
    // Test the code again, but now your function will get a different value when it calls the mocked package's function.
})

Svar #2

Jag använder följande mönster:

'use strict'

const packageToMock = require('../path')

jest.mock('../path')
jest.mock('../../../../../../lib/dmp.db')

beforeEach(() => {
  packageToMock.methodToMock.mockReset()
})

describe('test suite', () => {
  test('test1', () => {
    packageToMock.methodToMock.mockResolvedValue('some value')
    expect(theThingToTest.someAction().type).toBe(types.SOME_TYPE)

  })
  test('test2', () => {
    packageToMock.methodToMock.mockResolvedValue('another value')
    expect(theThingToTest.someAction().type).toBe(types.OTHER_TYPE)
  })
})

Förklaring:

Du gör en mock av klassen du försöker använda på testsuite-nivå, se till att mocken återställs före varje test och för varje test använder du mockResolveValue för att beskriva vad som kommer att returneras när mocken returneras

Svar #3

Ett annat sätt är att använda jest.doMock(moduleName, factory, options).

t.ex.

the-package-to-mock.ts:

export function methodToMock() {
  return 'real type';
}

toTest.ts:

import { methodToMock } from './the-package-to-mock';

export function someAction() {
  return {
    type: methodToMock(),
  };
}

toTest.spec.ts:

describe('45006254', () => {
  beforeEach(() => {
    jest.resetModules();
  });
  it('test1', () => {
    jest.doMock('./the-package-to-mock', () => ({
      methodToMock: jest.fn(() => 'type A'),
    }));
    const theThingToTest = require('./toTest');
    expect(theThingToTest.someAction().type).toBe('type A');
  });

  it('test2', () => {
    jest.doMock('./the-package-to-mock', () => ({
      methodToMock: jest.fn(() => 'type B'),
    }));
    const theThingToTest = require('./toTest');
    expect(theThingToTest.someAction().type).toBe('type B');
  });
});

enhetstestresultat:

 PASS  examples/45006254/toTest.spec.ts
  45006254
    ✓ test1 (2016 ms)
    ✓ test2 (1 ms)

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

källkod: https://github.com/mrdulin/jest-v26-codelab/tree/main/examples/45006254

Relaterade artiklar