React Testing Library - Testing a mock Axios request

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey how's it going it's Lee Halladay and today we are going to be looking more into the react testing library by Kent Dodds specifically we're going to be looking at how to test um an Axios Ajax call so we're gonna look into how to mock out that call how to deal with some asynchronous aspects of this of this test because with Axios you're always waiting for our results you're waiting for the promise to resolve and we're gonna look into how we can test that um if we look at the testing library's website they give an example I think it's down here in the example section and they sort of go through an example that's very similar to the one we're going to be looking at today they do it via click whereas we're just gonna do it when the component get surrendered but it's all the same sort of ideas so if you were looking at this and not quite sure what was going on we're going to step through it step by step today so let's take a look at the code so we're gonna work fully in the code editor here and the component we are going to test is over here on the left so it's a functional component that takes in a URL as a prop so whatever sort of URL string that we want to to fetch and the first thing we do is we set up using the use state hook some state that starts out as null and eventually it will contain the data from the fetch request so we also have a function that we can call anytime we want to modify that so when this function is rendered we want to fetch the URL and we can use the use effect hook for that so this code looks pretty complicated and I'm thinking of doing another short follow-up video after that steps through all this but all you basically need to know here is that this use effect hook performs the Axios request and when it gets the result it calls set data and puts the response data into that data so if that works we've sort of got two scenarios to deal with here we've got when there is not yet data so starts out as null comes down here and when it's not data we're gonna return just a little span that says loading data otherwise so when we do have data we're going to print out the greeting so the the URL we're fetching I'm just sort of making assumption since it's play data that it has a greeting and we'll render that into the span so we're going to look at how to write a test to test these different scenarios here so I've already set up a file fetched SJS and I've already just put the the imports here 90% because I can never remember so I so I don't look too bad on video but um we always new react because that's where protesting and we're writing some JSX code so that's a given we need to import three different functions from the react testing library the ability to render out the component we're testing a cleanup function that we can call after each test or better said jest will call for us after each test and wait for element as I mentioned we're testing asynchronous code so it might not be available sort of have the test the at the time the test runs so we need to wait for it to appear some custom expect testers to make it easier to test components we are importing Axios and I'll explain why I called it Axios mock in a little sec and then we're importing the component itself that we're working through so let's start writing our test so it fetches and displays data we need to make it a sink because we've got some async/await happening inside of here and we'll just close that off and okay so our test should pass because cuz there's it does nothing so that's that's good so far so the first thing we're gonna do is we're just gonna take care of this cleanup so just injects a function called after each that we can use globally so we're gonna say after each test call this cleanup function so that is done all right so what we want to do now is let's let's start by rendering out this component and putting it some helpers that it returns into a variable to use later on so we will say Const some stuff we're gonna destructor equals render the fetch component and if you remember the fetch aa receives a URL as its some prop so okay we're getting some nice errors over here on the right that's good so we'll set up a URL and we'll just say that it's gonna visit slash greeting which obviously doesn't exist but that's what we use for testing and we'll pass that in as the prop okay so cool I it's work so when we render surrender comes again from the react testing library when we render this function it will return us a number of sort of ways we can reach in and interact or or look at the whatever was rendered so we are going to use a function called a get by test ID okay so what this allows us to do is if any of our HTML implements the data believe it's just called test ID prop we can use this to access the span so that we can take a look inside of it and make sure that it's it's doing things correctly so we'll just call this this is the loading span so we can come back here now and we can write our first expect so we're gonna expect that when we say get by test ID loading that so this returns us the element and we can say to have text content so this to have text content comes from this library here which is why we can do that so when it's loading we expect it to have that text content loading data okay so we'll put that into a string and let's see if it's working okay it appears to be working because when it goes through the first time it actually renders this out before the use effect ever runs so the first time it goes through it will definitely show loading data no matter what and that's why it is working so now we want to move on and we want to test that the Ajax call is performed correctly so that when we have some data it renders out inside of this span here so the first thing we're gonna do is we'll just set up another data test ID and we'll call this one resolved so this will exist when we have data but we need to actually make Axios perform an ajax call or an HTTP request and during tests we don't actually want it to go across the internet and fetch some data because a that would be slow B whatever website we're pulling data from might get angry um so what we're gonna do is mock out Axios and also slash greeting wouldn't work anyways because uh that doesn't exist so we're gonna mock it out and the way you mocked stuff out in jest is that you can so I'm gonna open up my code here and I already have a folder inside of the SRC called underscore underscore mocks underscore underscore so if you ever want to mock out a module you can put it inside of the mocks special mocks folder and give it the same name so we'll call it Axios because that's what it is and we need to sort of export a mocked or faked version of this ech Axios module so we can say export default and we'll do an object and if you look how Axios is used it uses it calls the get function so we just need to make sure because right now we're only using get that we implement that so we will have it adjust function so that's like a faked out mock version of a function that we will have it resolved the value to something so whenever you call this it's sort of Auto resolves and it's going to have this value so we're gonna have data and then right now we'll just put our data as empty okay so just close this again because we don't need it give us some space so here's our sort of mocked out version of Axios so now in the test when we import Axios it's not actually importing the real Axios because it detected that mocks folder so I just named it Axios mock because just to make it clear that it's not the real one it's the fake one so what we can do is we can override sort of the global mock resolved value and give it a custom one just explicitly for this test so we can do that by saying Axios mock get and get is like this fake function here and we'll say mock result value once I believe it is so just the next time it's called one time return this special value as well of data and we'll have the greeting in that data say hello there and remember that this is expecting a greeting field to exist so that's why I set up the data that way okay so moving on the first time it renders through its gonna say loading content but then it's the use effect kicks in and it's gonna perform this Axios call which is going to resolve right away because we've mocked out Axios and it's going to update the state with whatever it was returned that modifying the state will force a rerender and it will come back down again and this time we will have data so it's going to return this last one here so if it all worked as planned we should be able to find this span by the data test ID and make sure that it has the correct value so we got a little bit of an issue and that issue is it doesn't appear right away it um because it's all asynchronous and we want to wait for that element to appear on the screen so that's why I had this imported up here wait for element so what we can say is we are waiting for the resolved span that's what we'll call the spam that we're gonna get and we're gonna wait for that element and what you do is you pass in an arrow function here that needs to return the element so we'll use get by test ID again and I believe it was called resolved okay I messed up one thing it reserves a promise so we want to wait for this thing to resolve so now we can come down here and we can expect that the results pan has to have text content so because we mocked it out right here we can just copy that down cool and it still works so let's add a couple more tests that are specific to making sure that the Mach was called correctly so what we can do is we can say we expect that the Axios mach dot get to have been called x cool so we expect it to have been called one time and we can also say Axios mach get to have been called with so this is like when you called get what arguments did it receive so it received when we passed in this URL greeting and that's what we passed to Axios get so we expected to have been called with the URL that I had popped into a variable up here and that's the whole thing our test is working from start to finish and just to go over this now that all the codes in place so the first thing we did is after import everything and cleaning up after each test we made sure that we're we've got an async function so that we can use a weight down here we mocked out the resolve value of our Axios get call to just be this hard coded data we set up our URL and we rendered our fetch component passing in that URL as a prop in return we got our get by test ID to dig into the whatever was rendered and find those elements so that we can test that they have different attributes or text values and we test it at the beginning that when there's no data yet that it says loading data then we wrote some code to wait for the result element to appear so as it triggers the use effect which updates the state it will rerender itself and eventually it will display that span on the screen and then once we have this span because we awaited it we can check that it has the right text content and that our Axios get was called once receiving the URL that we expected it to receive and that's the test from beginning to end hope you enjoyed the video right after this one I'm gonna record another one that goes into a little bit more detail about how this whole use effect thing works and why I set it up the way I did thanks I hope you enjoyed it take care bye
Info
Channel: Leigh Halliday
Views: 46,958
Rating: undefined out of 5
Keywords: react, testing, react-testing-library, mocks, axios
Id: Ngj2f1n9pUw
Channel Id: undefined
Length: 15min 21sec (921 seconds)
Published: Wed Feb 13 2019
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.