javascript - Como verificar múltiplos argumentos em múltiplas chamadas para spies do jest?
Eu tenho a seguinte função em um componente React:
onUploadStart(file, xhr, formData) {
formData.append('filename', file.name);
formData.append('mimeType', file.type);
}
Este é o meu teste que pelo menos faz com que o espião seja chamado:
const formData = { append: jest.fn() };
const file = { name: 'someFileName', type: 'someMimeType' };
eventHandlers.onUploadStart(file, null, formData);
expect(formData.append).toHaveBeenCalledWith(
['mimeType', 'someMimeType'],
['fileName', 'someFileName']
);
No entanto, a afirmação não está funcionando:
Expected mock function to have been called with:
[["mimeType", "someMimeType"], ["fileName", "someFileName"]]
But it was called with:
["mimeType", "someMimeType"], ["filename", "someFileName"]
Qual é a maneira correta de usar toHaveBeenCalledWith?
Resposta #1
Eu consegui simular várias chamadas e verificar os argumentos desta maneira:
expect(mockFn.mock.calls).toEqual([
[arg1, arg2, ...], // First call
[arg1, arg2, ...] // Second call
]);
onde mockFn é o nome da sua função mockada.
Resposta #2
Desde o Jest 23.0 existe .toHaveBeenNthCalledWith(nthCall, arg1, arg2, ....) https://jestjs.io/docs/expect#tohavebeennthcalledwithnthcall-arg1-arg2-
Também sob o pseudônimo: .nthCalledWith(nthCall, arg1, arg2, ...)
Se você tiver uma função mock, pode usar
.toHaveBeenNthCalledWithpara testar com quais argumentos ela foi chamada pela enésima vez. Por exemplo, digamos que você tenha uma funçãodrinkEach(drink, Array<flavor>)que aplicafa diversos sabores, e você quer garantir que, quando chamá-la, o primeiro sabor com o qual ela opera seja'limão'e o segundo seja'polvo'. Você pode escrever:
test('drinkEach drinks each drink', () => {
const drink = jest.fn();
drinkEach(drink, ['lemon', 'octopus']);
expect(drink).toHaveBeenNthCalledWith(1, 'lemon');
expect(drink).toHaveBeenNthCalledWith(2, 'octopus');
});
Nota: o n-ésimo argumento deve ser um número inteiro positivo começando a partir de 1.
Resposta #3
Você também pode testar toHaveBeenCalledWith e testar várias vezes para cada combinação de parâmetros esperada.
Um exemplo é que a API do plugin Google Analytics usa a mesma chamada de função com diferentes combinações de parâmetros.
function requireGoogleAnalyticsPlugins() {
...
ga('create', 'UA-XXXXX-Y', 'auto');
ga('require', 'localHitSender', {path: '/log', debug: true});
ga('send', 'pageview');
}
Para testar isso, o exemplo abaixo verifica que ga foi chamado três vezes com as várias combinações de parâmetros.
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');
});
});
No caso do OP, você poderia testar isso com
expect(formData.append).toHaveBeenCalledWith('mimeType', 'someMimeType');
expect(formData.append).toHaveBeenCalledWith('fileName', 'someFileName');
Resposta #4
A assinatura é .toHaveBeenCalledWith(arg1, arg2, ...), onde arg1, arg2, ... significa em uma chamada única (veja).
Se você quiser testar várias chamadas, basta expect várias vezes.
Infelizmente, ainda não encontrei um método para testar a ordem de várias chamadas.
Resposta #5
Você também pode criar um array dos argumentos esperados por chamada e percorrê-lo:
const expectedArgs = ['a', 'b', 'c', 'd']
expectedArgs.forEach((arg, index) =>
expect(myFunc).toHaveBeenNthCalledWith(index + 1, arg))
Esta solução considera a ordem das chamadas. Se você não se importar com a ordem, pode usar toHaveBeenCalledWith sem o índice.
