There are several ways to mock APIs for our tests.
Here we're using jest.mock with the module factory parameter to a new mocked module to replace our original. This helps us avoid problems like servers taking a long time and node.js not having fetch built-in.
When using mocks this way it's important to note that this mocked module is only going to show up for the tests executed in this file. Other test suites will continue to receive the original implementation of app/api.
Other approaches to mock APIs include mocking out window.fetch
or using Mock Service Worker to provide a more robust API implementation. However, the approach we took here makes sense for our use case. We have a simple API surface, it lives in a single file, we never call fetch
directly and we don't need a lot of bells and whistles (like responding to different routes or query parameters). So for that reason this approach and the spyOn approach used in some of the later lessons actually works really well.
If you're using Apollo or ReactQuery or SWR to handle your data, then you almost certainly should use Mock Service Worker instead of the jest.mock approach.
Instructor: Open up cartslice.test.ts, and at the top of the file import star as API from app/API. Below that, let's add a new test. It'll just say, checkout should work. This will take an async arrow function. In that test, type await API.checkout fake item four.
Now on the right hand side of the screen, we're going to go ahead and run NPX jest in watch mode and we'll use the cartslice pattern to only run this file. You see that our test has failed because fetch is not defined.
If you open up API.ts, you see that we rely on fetch, which is a browser API that doesn't exist natively in node. There are a number of ways to fix this but the easiest way for us to fix it is to mock out the entire API surface.
At the top of our file type, jest.mock../../app/API, and we'll pass in a function. That function is going to return an object with two properties. It's an async method called getProducts and an async method called checkout.
Checkout is going to take items, switch default to an empty object, and we need a comma in between these two. In our getProducts method, we're just going to return an array. In our checkout method, we're going to have a little bit more logic.
Type const empty = object.keysitems.length triple = 0. We're going to check if it's empty. If it is empty, we're going to throw a new error, must include cart items. This is actually similar logic to what our API does, but since we're mocking out, we need to recreate it here.
Then if items.bad, item is greater than zero, turn success false. Otherwise, return success true. Here we're mocking out our API. You can see just by mocking that out, our checkout test is already passing, but you will notice that we are having some typescript errors.
We need to properly type the argument here items. We can simply say API.cart items. With that, our tests are passing and typescript is happy.
Member comments are a way for members to communicate, interact, and ask questions about a lesson.
The instructor or someone from the community might respond to your question Here are a few basic guidelines to commenting on egghead.io
Be on-Topic
Comments are for discussing a lesson. If you're having a general issue with the website functionality, please contact us at support@egghead.io.
Avoid meta-discussion
Code Problems?
Should be accompanied by code! Codesandbox or Stackblitz provide a way to share code and discuss it in context
Details and Context
Vague question? Vague answer. Any details and context you can provide will lure more interesting answers!