Diferenças entre o jest.spyOn e jest.mock
Tags: jest, testing, javascript, mock
Published: 2024-06-21 12:02:18

Sim, existem diferenças importantes entre `jest.mock` e `jest.spyOn`, embora ambos sejam usados para criar mocks em testes. Vamos explorar as diferenças e quando usar cada um.

## **jest.mock**

### Uso
`jest.mock` é usado para mockar módulos inteiros. Isso é útil quando você deseja substituir um módulo completo, seja ele uma biblioteca de terceiros ou um módulo local, com uma versão mockada.

### Comportamento
Quando você usa `jest.mock`, Jest automaticamente substitui todas as funções exportadas pelo módulo mockado com versões mockadas.

### Exemplos
```javascript
// Suponha que temos um módulo `utils.js` com uma função `calculate`.
import { calculate } from './utils';

// Testando um componente que usa a função `calculate`.
import MyComponent from './MyComponent';

// Mocka o módulo `utils`.
jest.mock('./utils', () => ({
  calculate: jest.fn(),
}));

test('should call calculate function', () => {
  calculate.mockReturnValue(42);
  render(<MyComponent />);
  expect(calculate).toHaveBeenCalled();
});
```

### Quando Usar
Use `jest.mock` quando você quiser mockar todas as funções de um módulo ou quando quiser substituir completamente um módulo.

## **jest.spyOn**

### Uso
`jest.spyOn` é usado para espionar métodos em objetos. Isso é útil quando você deseja manter a implementação original do método, mas ainda assim observar como ele é chamado e/ou fornecer valores de retorno personalizados.

### Comportamento
`jest.spyOn` cria uma versão mockada de uma função existente, permitindo que você mantenha a implementação original ou a substitua conforme necessário.

### Exemplos
```javascript
// Suponha que temos um módulo `utils.js` com uma função `calculate`.
import * as utils from './utils';

// Testando um componente que usa a função `calculate`.
import MyComponent from './MyComponent';

test('should call calculate function', () => {
  // Espiona a função `calculate`.
  const spy = jest.spyOn(utils, 'calculate').mockReturnValue(42);
  render(<MyComponent />);
  expect(spy).toHaveBeenCalled();
});
```

### Quando Usar
Use `jest.spyOn` quando você quiser espiar uma função específica em um módulo sem substituir todo o módulo. É especialmente útil quando você quer observar chamadas para métodos em instâncias de classes ou objetos específicos.

## Comparação Direta

### **jest.mock**

- **Escopo**: Mocka módulos inteiros.
- **Substituição**: Substitui todas as funções exportadas pelo módulo com versões mockadas.
- **Uso**: Ideal para mockar bibliotecas de terceiros ou módulos locais inteiros.

### `jest.spyOn`

- **Escopo**: Espiona métodos específicos em objetos ou instâncias de classes.
- **Substituição**: Cria uma versão mockada de uma função existente, permitindo observar chamadas e substituir o comportamento.
- **Uso**: Ideal para observar e mockar métodos específicos em objetos ou instâncias, mantendo a implementação original disponível.

## Exemplo Completo

### Arquivo `utils.js`
```javascript
export const calculate = (a, b) => a + b;
```

### Arquivo `MyComponent.js`
```javascript
import React from 'react';
import { calculate } from './utils';

const MyComponent = () => {
  const result = calculate(2, 3);
  return <div>{result}</div>;
};

export default MyComponent;
```

### Teste com `jest.mock`
```javascript
import React from 'react';
import { render, screen } from '@testing-library/react';
import MyComponent from './MyComponent';
import { calculate } from './utils';

jest.mock('./utils', () => ({
  calculate: jest.fn(),
}));

test('should call calculate function', () => {
  calculate.mockReturnValue(42);
  render(<MyComponent />);
  expect(calculate).toHaveBeenCalled();
  expect(screen.getByText('42')).toBeInTheDocument();
});
```

### Teste com `jest.spyOn`
```javascript
import React from 'react';
import { render, screen } from '@testing-library/react';
import MyComponent from './MyComponent';
import * as utils from './utils';

test('should call calculate function', () => {
  const spy = jest.spyOn(utils, 'calculate').mockReturnValue(42);
  render(<MyComponent />);
  expect(spy).toHaveBeenCalled();
  expect(screen.getByText('42')).toBeInTheDocument();
});
```

## Conclusão

Tanto `jest.mock` quanto `jest.spyOn` são ferramentas poderosas no Jest para mockar funções e módulos. A escolha entre eles depende do contexto do teste e do que você está tentando alcançar. `jest.mock` é ótimo para substituir módulos inteiros, enquanto `jest.spyOn` é ideal para observar e mockar métodos específicos sem substituir todo o módulo.