- [Presenter] So far, we've mocked a single function.
Let's mock an entire module with Jest,
but how does it work?
in no Jest and in most languages,
units of code usually have dependencies.
That's a good thing,
because it promotes re-usability and modularity.
As an example, our application has dependencies
on the sequel light database
and the debugger module for logging.
Of course, you can write tests that use other components,
but testing dependencies isn't unit testing,
it's integration testing.
So, how do we isolate a unit with the dependency?
The solution is to manipulate no Jests require cash
by substituting your own code
in place of the target dependency.
The nice thing about this technique,
is that it needs no code changes
to the target require to work.
Like many other forms of monkey patching
and JavaScript Manipulation,
changes to the require cash can be done manually.
With that said, doing it yourself head hoc
is messy and fragile at best.
Fortunately, Jest provides a simple way to do this.
jest.mock accepts a module's name as its first argument.
This can be the relative path to a module
if it's within your project,
or the community package or core module name.
By default, jest.mock
will match the signature of the mock module
and return mocks instead.
For example, if module.exports
returned an anonymous function, which returned to value,
the mocked function
would return a Jest mock function instead.
If it exports an object with properties, foo and bar,
both foo and bar would be mock functions.
There are two other optional arguments,
factory and options.
Factory overrides Jests auto mocking feature,
allowing you to return whatever structure you want,
which doesn't have to match the target module.
If you wanted to use factory,
provided with a function like an error function expression
that returns the desired structure.
The last argument is options,
which can be used to create virtual mocks
for generated modules that don't exist within the system.
We're not going to be using virtual mocks
within this course.
In order to use jest.mock,
you need to mock the module before it's required.
As an example, we'll use the relative path to reservations,
then require it.
Practically speaking,
use jest.mock with the name of the module,
then require the module.
There's an inverse,
when you're done you should unmock any mock modules.
Similar to jest.fn,
forgetting to do so will have an adverse effect.
The syntax is straightforward, jest.unmock,
then the module name.
Before we see mock in action,
we're going to add some structure to our test file
in order to prepare for tests and clean up afterwards.
There are functions that can be defined,
beforeAll, which runs before all tests have started,
beforeEach, which runs before each test,
afterAll, which will run after all the tests in a file
or group have completed,
and afterEach, which runs after each test.
Each takes a function as an argument,
which performs the task
and an optional timeout in milliseconds
to wait before aborting.
Within our test suite for reservations,
instead of requiring the reservations file at the top,
we're going to use let, within the described scope
to define a variable named reservations,
then we can use beforeAll to set reservations
to whatever is needed.
If we want to mock it, we'll just call jest.mock first,
then assign the variable to require the module.
If we don't want to mock,
we'll just set the variable to require the module.
Ready to get mocking, switch to vs code.
Open up reservations.test.js.
At the top, let's start with a new group
that we're going to describe for fetch,
and then an error function expression.
Fetch just returned some reservations.
Practically, there's no logic to test,
but it's a good example of how mocking works
and it will provide the foundation
for more complicated use cases.
We'll use, let, for reservations.
Then, we're going to use beforeAll,
which takes an argument of a function,
which will use jest.mock for reservations
using the relative path.
And then reservations equals require reservations.
We'll add a trailing semi-colon,
then we'll add an afterAll
with a error function expression,
and then we'll use jest.unmock,
and then again, the path to the module,
the relative path of .reservations at a trailing semi-colon,
then a test, it should be mocked
and not create a database record,
an error function expression
and then expect reservations.fetch
and we'll execute it.
And we're just going to make sure that it does nothing.
So use the matcher to be undefined,
add trailing semi-colons.
Since we removed the require reservations up at the top,
we're going to have retrofit
our two remaining described groups.
So I'm going to copy and paste the reservations equals.
And in the describe validate up at the top,
let reservations, plural, and then add some new lines
beforeAll parentheses,
and then we'll execute the anonymous function,
reservations equals require reservations.
We can copy and paste this,
and paste it into create,
save the file, then open up the terminal, MPM test.
Do you want to see the consequences?
If you don't unmock the module, scroll up to the top.
So in the afterAll, let's comment that out
and type MPM test.
We've got no less than three errors
because we didn't unmock the module,
and we changed the signature of how things worked.
Remove the comment out, save the file MPM test,
and make sure that the changes worked.
Fantastic, that sorted out.
Close out the terminal and any remaining code files.
We've mocked modules that we're requiring,
but, what if we want to mock module dependencies
within what we're requiring.