Mocking Axios in Jest + Testing Async Functions

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey how's it going everyone today we've got a video where we're going to be testing this function right here in front of us and this functions got a couple things going on that makes it a little bit tricky to test the first thing is that it is asynchronous so it returns us a promise and the second thing that we need to deal with is that the reason it's asynchronous is because it uses Axios to make an AJAX request uh specifically an HTTP GET request and that becomes difficult because in our test we don't actually want to make the real HTTP request because a it's really slow be Axios might get angry that every time we run our test we're hitting their server and see their certain requests you can't make all the time when you're testing such as charging a credit card and things like that so we need a way to solve both asynchronous function and a way to mock Axio so that we can almost have like a fake version of it that always returns us right away the thing that words were expecting so let's get in here and just start writing a test for it so we're gonna create a new folder called underscore underscore tests underscore underscore and in here we'll create a file called unsplash is which is the file that we are testing so let's come in here and since we're testing the unsplash function let's import it so uh import on splash from unsplash and actually before I forget if you'd like to follow along with this code and the video if you follow the link below this video it will take you to my blog where I'll have a link to the code in the state where we're at like right now when we began right at the beginning and also a finished version of the code if you want to just follow along and then have the the final version as a reference okay so let's keep going we've imported our unsplash function and next thing we need to do is write our test so we'll say that it calls Axios and returns images and we'll do our arrow function here and here we can call our code so const images equals unsplash unsplash and we'll search for some kittens cool so let's just see what we're getting back so let's just console that log and then we'll start fixing errors as they occur so we'll come to the command line and we'll run yarn test all right and we get an error unsplash is not a function okay what am I doing wrong oh it's kids it's in the folder above and a bigger air all right so we got a network error um and I think what's basically happening is we're trying to call Axios but it can't for some reason work when we're running our tests it just gives us an error so right away we need a way to basically use Axios in this test but not the real Axios a fake version of it so let's come back to our code and what we're gonna do is in the SRC folder which is sort of the main route where all this code lives well that's anyways the case in a create react app and specifically the library we're using is just to run our tests so in this SRC folder we will create a folder called underscore underscore mocks underscore underscore so in here is where you can put mock modules that you want to use in your code during your tests so it's so specifically the module we want to mock is Axios so that's why we'll come here and and create a fake Axios module so let's just start by exporting an object like that so how does this how should this fake Axios look well if we come to our code we can see that Axios is a module or we'll just say an object that has a get property on it which is a function so the real Axios makes the full-on HTTP request but we need to make a fake version of this get function so we come back here and we'll define get property that can be a function but instead of just having like a normal arrow function we're actually going to use some just functionality to create a fake function that sort of it's it's referred to as a mock function or a spy function and it's just a fake function but it has some special special capabilities like you can ask it questions after it's been called like how many times were you called what arguments were you called with and you can provide a fake value to return whenever it's called so here we will pass an arrow function and because the real Axios returns a promise we need to deal with that as well in our fake Axios so what we're gonna do is just instantly resolve this promise and we need to pass to this resolved function the data we want it to resolve with so Axios resolves with an object that has a data property and for now we'll just say that our data is no so imagine the server is responding with literally nothing so now we can come back here and we can run our test again and we'll see what it gives us okay so cannot read property results of no so if you look at our test it calls Axios but remember it's not the real Axios anymore it's our fake one waits for the response we're good so far puts the response here and then this response gets data but our data was null so as soon as we did null dot results we get an error because that doesn't work so let's just say that the server responds to us within with an empty object so we'll run our test again and see what it gives us cool so this time it's working well saying it past anyways but you can see here we had a console dot log statement and what we're logging is the thing that's returned from our function so we call unsplash its return something we're saying it's called images and then we log that but what it's telling us that it got back was a promise which is makes sense because this unsplash function is asynchronous so anytime you have an async await function the thing it returns back to you is a promise that you need to then say dot then to or in our case we can actually make our test be async await as well so we do that by just defining this test as async here and now we can await the result from our unsplash function so now when we come back here we see that the result is undefined the images are undefined that we got back from our unsplash function so why is that the case well we just had an empty object and in our code we which is what data represents and we asked it for results and there weren't any so we need to fix that so here you could simply say okay well then results is an empty array or whatever but just to make this code a little bit more reusable let's actually leave this fake Axios as it is and we'll come into our test and we'll override the fake Axios just for this test so we're gonna want to import it so import Axios from Axios and remember because we've mocked Axios here in this mocks folder what we get back isn't the real Axios but the fake one so let's just give it a different name so that it's clear to us what we're dealing with mock Axios so we come down here and mocks axial MOC Axios has a get function and because get is a jest MOC function it has some functionality that says MOC implementation once so basically override what was going on he over here and we're gonna provide a new mop that's just going to be used once so we'll pass an arrow function to this and we'll resolve a promise right away and it will have the same data that this time we'll have results and we can say that it's an array of images and we'll just say because we're searching kittens will cute JPEG like that so now when we call unsplash it's going to instead I use this mahkum implementation and now because we've provided a specific result that matches what we would get back from Axios or enough from Axios from unsplash api we should get this array here in the images variable so we'll come back here and in our console the log we can see that it is now returning what we mocked out in our mock Axios so let's write an actual test now so because we know that we expect to get back this I'll just copy it and then I'll come down here and I'll say expect images to equal that array so I'll just hit a to rerun the test and you can see that it's now passing and the test only took two milliseconds to run so it's obvious it's not making the real HTTP request because there's no way it would respond within two milliseconds if that were the case so you can sort of see that I've got a lot going on in this test now and I like to split this up into three sections so I call this the setup so anything you need to do sort of pre test here's the actual work of our test so like run the code you're trying to test and down here you've got your assertions or your expects so this is after you've actually done the worker you've called the function and you want to make sure that everything worked as planned so we're gonna write a couple more expect so now we can say we expect mock Axios get so that's that jest dot FN a mock function and we're gonna say to have been called x one so what this says is we reach into our mock Axios and we get it's a get property which is that just function and because we called unsplash once right here we should expect that this function was called one time so we come back here and we see that now our test is working again but now we're making sure that Axios was called the correct amount of x and if we want to go further we can make sure that we were passing the correct parameters to MA Axios get so we could write another expect clause so expect mock Axios get to have been called with and for just gonna put an empty string here and the test is gonna fail and but first what what is this basically this allows us to look at the arguments or the parameters that were passed to the Axios get function when it was called so we come down here it's failing because it didn't receive an empty string what it actually received was the URL we were calling it with so we'll just put that here as the first parameter and the second parameter was this object here and we'll save that so now everything is passing again because this was these were the exact arguments that the axial state function was called with and if you don't want to keep your client code here in your tests probably a good idea we can do the same thing we did in our unsplash function we can just access the environment variable so process n dot react tap on splash token , and it's working again everything's passing and just to go over this quickly with webpack and especially the Crete react up setup you can have it read some environment variables that are either set in the actual environment or that live in a dot and file that you don't put in your in your actual git repository so if you look at the git ignore here you can see the word ignoring the dot add and file and so create react app is specifically configured to bring in any environment variables that begin with react app like this so we put this in our end dot end file we can come back here and access that through the node process dot N and then we can access the react app on splash token environment variable so now we have tested this function I'd say pretty well and just to review we start at the top with our imports so we imported mock Axios because we're going to use it and specifically access the get function that we were mocking we imported on splash which is the function we're testing and then we wrote our jest test we had to make this test asynchronous because it calls asynchronous code inside that returns a promise so we wanted to be able to wait for that promise to resolve so that's the first thing but we started this test with some setup and we overrode our mock Axios get function to basically provide it a mock implementation that we want it to use one time so when it's called for one time it will return as the result of this arrow function here which is a promise that resolves instantly and returns us an object that sort of mimics the Axios response and in the data object part of it it mimics what the unsplash api would return their results array is obviously filled with things that are bigger objects not just a string this is cute JPEG but just for the purpose of this test we're fine because we just wanted to make sure that when we do the work of this function so we call the unsplash function because it returns a promise we want to await so await it that it resolves and put the images here now that we have the images in a variable we can expect that they're equal to what we were expecting and we know exactly what to look for because we provided a mock implementation just above here so you could even put this in a variable so you just reference the same variable twice if you want then we specifically made a few couple expectation calls dealing with our get Mach function so we checked that Axios get was indeed called one time and that we checked that it was called with the arguments the URL that we wanted it to reach and then it was given all the different parameters that we were expecting to be sent to the API and what we've ended up with is a function or a test that runs a asynchronous function very quickly but it does a mock call to Axio so that we didn't have to make a real HTTP request within our tests so that's it I hope you enjoyed this video and have a great day bye
Info
Channel: Leigh Halliday
Views: 59,777
Rating: 4.9442024 out of 5
Keywords: javascript, testing, mocks, async/await, promises, axios
Id: 9Yrd4aZkse8
Channel Id: undefined
Length: 17min 42sec (1062 seconds)
Published: Fri Apr 13 2018
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.