javascript - Como redefinir ou limpar um spy no Jest?
Eu tenho um espião que é usado em múltiplas asserções em múltimos testes em uma suíte.
Como faço para limpar ou redefinir o espião para que em cada teste o método que o espião intercepta seja considerado como não tendo sido invocado?
Por exemplo, como fazer a asserção em 'não executa o método' ser verdadeira?
const methods = {
run: () => {}
}
const spy = jest.spyOn(methods, 'run')
describe('spy', () => {
it('runs method', () => {
methods.run()
expect(spy).toHaveBeenCalled() //=> true
})
it('does not run method', () => {
// how to make this true?
expect(spy).not.toHaveBeenCalled() //=> false
})
})
Resposta #1
Obrigado ao @sdgluck pela resposta, embora eu queira acrescentar a esta resposta que, no meu caso, eu queria um estado limpo após cada teste, já que tenho vários testes com o mesmo espião. Então, em vez de chamar o mockClear() no(s) teste(s) anterior(es), eu o movi para o afterEach() (ou você pode usá-lo com beforeEach) assim:
afterEach(() => {
jest.clearAllMocks();
});
E finalmente, meus testes estão funcionando como deveriam sem que o espião seja chamado do teste anterior. Você também pode ler a documentação deles sobre esse recurso.
Opção 2
Se você quiser fazer isso em nível global, você também poderia atualizar seu jest.config.js (ou do package.json), o que limpará o spy em cada teste, mas sem precisar chamar jest.clearAllMocks() em cada teste.
module.exports = {
clearMocks: true,
// ...
}
Você pode ler a documentação do Jest sobre este recurso.
Resposta #2
Os spies do Jest têm a mesma API que os mocks. A documentação para mocks está aqui e especifica um método mockClear que:
Redefine todas as informações armazenadas nos arrays
mockFn.mock.callsemockFn.mock.instances.Isso muitas vezes é útil quando você quer limpar os dados de uso de um mock entre duas afirmações.
(ênfase minha)
Então, podemos usar mockClear para "resetar" um espião. Usando seu exemplo:
const methods = {
run: () => {}
}
const spy = jest.spyOn(methods, 'run')
describe('spy', () => {
it('runs method', () => {
methods.run()
expect(spy).toHaveBeenCalled() //=> true
/* clean up the spy so future assertions
are unaffected by invocations of the method
in this test */
spy.mockClear()
})
it('does not run method', () => {
expect(spy).not.toHaveBeenCalled() //=> true
})
})
Aqui está um exemplo no CodeSandbox.
Resposta #3
Caso você queira restaurar o comportamento original de um método que você havia adicionado anteriormente a um spy, você pode usar o método mockRestore.
Confira o exemplo abaixo:
class MyClass {
get myBooleanMethod(): boolean {
return true;
}
}
const myObject = new MyClass();
const mockMyBooleanMethod = jest.spyOn(myObject, 'myBooleanMethod', 'get');
// mock myBooleanMethod to return false
mockMyBooleanMethod.mockReturnValue(false);
// restore myBooleanMethod to its original behavior
mockMyBooleanMethod.mockRestore();
Resposta #4
Iterando ainda mais sobre a resposta de @ghiscoding, você pode especificar clearMocks na configuração do Jest, o que é equivalente a chamar jest.clearAllMocks() entre cada teste:
{
...
clearMocks: true,
...
}
Veja os documentos aqui.
