Funções de simulação ( mocks em inglês ) permitem que você teste os links entre códigos, apagando a implementação real de uma função, capturando chamadas para a função (e os parâmetros passados nessas chamadas), capturar instâncias do construtor de funções quando instanciado com
new, e permitindo configuração em tempo de teste de valores de retorno.
There are two ways to mock functions: Either by creating a mock function to use in test code, or writing a
manual mock to override a module dependency.
Vamos imaginar que estamos testando uma implementação de uma função
forEach, que invoca uma "callback" para cada item em um array fornecido.
Para testar esta função, podemos usar uma função de simulação e inspecionar o estado da simulação para garantir que a "callback" é invocada como esperado.
All mock functions have this special
.mock property, which is where data about how the function has been called and what the function returned is kept. The
.mock property also tracks the value of
this for each call, so it is possible to inspect this as well:
These mock members are very useful in tests to assert how these functions get called, instantiated, or what they returned:
Mock functions can also be used to inject test values into your code during a test:
Mock functions are also very effective in code that uses a functional continuation-passing style. Code written in this style helps avoid the need for complicated stubs that recreate the behavior of the real component they're standing in for, in favor of injecting values directly into the test right before they're used.
Most real-world examples actually involve getting ahold of a mock function on a dependent component and configuring that, but the technique is the same. In these cases, try to avoid the temptation to implement logic inside of any function that's not directly being tested.
Suppose we have a class that fetches users from our API. The class uses axios to call the API then returns the
data attribute which contains all the users:
Now, in order to test this method without actually hitting the API (and thus creating slow and fragile tests), we can use the
jest.mock(...) function to automatically mock the axios module.
Once we mock the module we can provide a
.get that returns the data we want our test to assert against. In effect, we are saying that we want
axios.get('/users.json') to return a fake response.
Subsets of a module can be mocked and the rest of the module can keep their actual implementation:
Still, there are cases where it's useful to go beyond the ability to specify return values and full-on replace the implementation of a mock function. This can be done with
jest.fn or the
mockImplementationOnce method on mock functions.
mockImplementation method is useful when you need to define the default implementation of a mock function that is created from another module:
When you need to recreate a complex behavior of a mock function such that multiple function calls produce different results, use the
When the mocked function runs out of implementations defined with
mockImplementationOnce, it will execute the default implementation set with
jest.fn (if it is defined):
For cases where we have methods that are typically chained (and thus always need to return
this), we have a sugary API to simplify this in the form of a
.mockReturnThis() function that also sits on all mocks:
You can optionally provide a name for your mock functions, which will be displayed instead of "jest.fn()" in the test error output. Faça uso dessa opção se você quiser ser capaz de rapidamente identificar a função simulada que reportou um erro no resultado do seu teste.
Finally, in order to make it less demanding to assert how mock functions have been called, we've added some custom matcher functions for you:
These matchers are sugar for common forms of inspecting the
.mock property. You can always do this manually yourself if that's more to your taste or if you need to do something more specific:
Para obter uma lista completa de "matchers", confira a documentação de referência.