Pesquisa de site

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.calls e mockFn.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.

Artigos relacionados