javascript - Hvordan sjekke flere argumenter på flere kall for jest spioner?


Jeg har følgende funksjon i en React-komponent:

onUploadStart(file, xhr, formData) {
  formData.append('filename', file.name);
  formData.append('mimeType', file.type);
}

Dette er testen min som i det minste får spionen til å bli kalt:

const formData = { append: jest.fn() };
const file = { name: 'someFileName', type: 'someMimeType' };
eventHandlers.onUploadStart(file, null, formData);

expect(formData.append).toHaveBeenCalledWith(
  ['mimeType', 'someMimeType'],
  ['fileName', 'someFileName']
);

Imidlertid fungerer ikke påstanden:

Expected mock function to have been called with:
 [["mimeType", "someMimeType"], ["fileName", "someFileName"]]
But it was called with:
  ["mimeType", "someMimeType"], ["filename", "someFileName"]

Hva er riktig måte å bruke toHaveBeenCalledWith på?

Svar #1

Jeg kunne mocke flere kall og sjekke argumentene på denne måten:

expect(mockFn.mock.calls).toEqual([
  [arg1, arg2, ...], // First call
  [arg1, arg2, ...]  // Second call
]);

hvor mockFn er navnet på din mockede funksjon.

Svar #2

Siden jest 23.0 finnes det .toHaveBeenNthCalledWith(nthCall, arg1, arg2, ....) https://jestjs.io/docs/expect#tohavebeennthcalledwithnthcall-arg1-arg2-

Også under aliaset: .nthCalledWith(nthCall, arg1, arg2, ...)

Hvis du har en mock-funksjon, kan du bruke .toHaveBeenNthCalledWith for å teste hvilke argumenter den ble kalt med som nr. n. For eksempel, la oss si at du har en drinkEach(drink, Array<flavor>)-funksjon som bruker f på en rekke smaker, og du vil forsikre deg om at når du kaller den, er den første smaken den opererer på 'lemon' og den andre 'octopus'. Du kan skrive:

test('drinkEach drinks each drink', () => {
  const drink = jest.fn();
  drinkEach(drink, ['lemon', 'octopus']);
  expect(drink).toHaveBeenNthCalledWith(1, 'lemon');
  expect(drink).toHaveBeenNthCalledWith(2, 'octopus');
});

Merk: det n-te argumentet må være et positivt heltall som starter fra 1.

Svar #3

Du kan også teste toHaveBeenCalledWith og teste flere ganger for hver forventet parameterkombinasjon.

Et eksempel er at Google Analytics-plugin API bruker det samme funksjonskallet med forskjellige parameterkombinasjoner.

function requireGoogleAnalyticsPlugins() {
  ...
  ga('create', 'UA-XXXXX-Y', 'auto');
  ga('require', 'localHitSender', {path: '/log', debug: true});
  ga('send', 'pageview');
}

For å teste dette sjekker eksemplet nedenfor at ga har blitt kalt tre ganger med de ulike parameterkombinasjonene.

describe("requireGoogleAnalyticsPlugins", () => {
  it("requires plugins", () => {
    requireGoogleAnalyticsPlugins();
    expect(GoogleAnalytics.ga.toHaveBeenCalledTimes(3);
    expect(GoogleAnalytics.ga).toHaveBeenCalledWith('create', 'UA-XXXXX-Y', 'auto');
    expect(GoogleAnalytics.ga).toHaveBeenCalledWith('require', 'localHitSender', {path: '/log', debug: true});
    expect(GoogleAnalytics.ga).toHaveBeenCalledWith('send', 'pageview');
  });
});

I OP-tilfelle kunne du teste dette med

expect(formData.append).toHaveBeenCalledWith('mimeType', 'someMimeType');
expect(formData.append).toHaveBeenCalledWith('fileName', 'someFileName');

Svar #4

Signaturen er .toHaveBeenCalledWith(arg1, arg2, ...), hvor arg1, arg2, ... betyr i en enkel kall (se).

Hvis du vil teste flere kall, bare forvent det flere ganger.

Dessverre har jeg ennå ikke funnet en metode for å teste rekkefølgen på flere kall.

Svar #5

Du kan også opprette et array med de forventede argumentene per kall og løpe gjennom det:

const expectedArgs = ['a', 'b', 'c', 'd']
expectedArgs.forEach((arg, index) => 
    expect(myFunc).toHaveBeenNthCalledWith(index + 1, arg))

Denne løsningen tar hensyn til rekkefølgen på kallene. Hvis du ikke bryr deg om rekkefølgen, kan du bruke toHaveBeenCalledWith uten indeks i stedet.

Relaterte artikler