Unit testing in JavaScript Part 4 - Mocking basics

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
Monday morning in the last episode we factored our vanilla JavaScript test suite to use the test runner Jes instead in this video we are going to make some addition to our actual code the tested code and add some code that a synchronously fetches data from a web service and in order to do that we are going to mock that call which means that today's episode is about mocking I and mpj and you are watching fun fun function [Music] [Music] [Music] alright so if you're a regular viewer you might notice that I'm in a new space this is my new studio space that is dedicated for just fun fun function there's no I have not done any sound or anything of this space yet I just arrived yesterday and that's why there's so much echo that's gonna be fixed in in the coming videos and also not too exciting might have to do something about that as well and also I'm not sure about the angle or anything really it's gonna be exciting I'm gonna make this a bit more cozy and then would probably do a full studio tour of this space I'm super excited about it it feels really good to have like a probable work place to go to and yeah it's gonna be great anyway today we are going to explore MOC functions MOC functions are fake functions that we use in place of doing a real network or database call or perhaps not do a call to a payment API in our tests we do this because we need to run unit tests and other automated tests in general hundreds and hundreds and hundreds of times and we need to run them very fast so in some cases it's just impossible to use a real payment err real API for instance in like we can do 200 tests credit card transactions and even if they provide us with a test API we were like it would be very very slow to keep doing real Network calls all the time because if you've run a unit testing suite it usually has like four to seven hundred tests and you want to be able to run those and in minutes or preferably seconds and that if you just involved involve the network calls and that yes becomes totally unfeasible also Network calls tends to fail some other time which means that your test suite ends up being brittle and like you run 400 thousands one has felt there and you run for an chest and one test fails there and it's just yeah mock functions return fake values and mock functions also allow us to inspect the mock function after we've completed running the test so that we can check that the mock function was called in the way that we expected it to be so let's have a look at a problem that we need Marx to solve all right here we have our old friend from the last episodes our order total function let me add a line break here yeah because that's nicer when dealing with e-commerce systems we need to deal with tax right and in Europe we have this thing called value-added tax which is kind of similar similar to sales tax in the US and the complexity of this is that when you sell to a person in another EU country you need to charge them the sale tax that's the vit the value-added tax that is applicable in their country so if you are selling to Germany you need to charge 19 percent tax and register that and you need to if you sell to somebody in the UK you need to sell them sell them at 20 percent vit until they exit the European Union where the brexit so these rates they change around they they are not stable for all the eternity so yes we can't just hard code them and hope that they never change thankfully there are some services that handle this for us such as the service that we're going to use today which is that API dot-com the very first thing that I would like to do before doing any kind of coding has to get a little bit acquainted with this API I always like to do this the very first thing when I get exposed to new API so what we're going to do is to call the VAT API completely isolated from all our other code and or total and all those concerns and check it out separately I will elaborate on why we do it like that in a little bit but but for now we are not going to jump ahead into coding tests or code we're going to look at the API okay so let's have a look here on that API dot-com and if we look here and here they listed like examples of different API calls we are going to do the use this the country code lookup and here are some PHP but what we are interested here in is this JSON response that we get so it's gonna be status you're gonna get the kind of code blah blah blah blah and here this is the value that we are interested in so from Luxembourg Luxembourg we have the valid it's 70% vit so it's under there is no there is a rates object which contains our well it contains a standard standard object which in turn contains a value and then it contains a bunch of other as well reduced and alt and super super reduced oh for ebooks they have a lower battery ebooks very interesting either way this is the one we're interested in okay so let's create a new file sandbox storge and I'm going to start I'm using this thing called Quokka which is really handy it's it's a plugin to do inline evaluation of JavaScript and I find it really nice when you're playing around with the code and also doing these videos very nice just playing around with things so we first we are going to need fetch this is an old environment so we we need no defects otherwise we won't have access to fetch and let's see let's do coal fetch no hang on I'm good put this in a result and salt it's not the fine of course and let's do a fetch and we need and let's go back to the thingy where'd you go so this is the end point you know let me steal that copy paste paste that in that's PHP we don't want PHP for now I'm just going to use de for that Deutschland or Germany so so far we have some result here let's see let's see what that is because we want the response dot txt all right cool it's status for a-1 authentication required mmm let's go back look at the docs API key and we need some header thing mm-hmm API key okay so what we need to do is it needs temple that location header as well if I key I think like here they actually use an uppercase a and I happen to know that according to the HTTP standard point or H better yeah it should be these these are required to be cases is it fun fact if you're building an API either way I have already put this thing in my environment variables did to do and I think I put it as in fact API key God there this is this is just so that you don't see my API key and but if you're doing this yourself you can just paste your API key here that you generate on a VAT API does call anyway does that help us does no we still get authentication required uh-huh oh wait I'm not actually I'm just passing this in as an option if I must actually tell fish that it's these this is a header sorry fetch I keep assuming that you okay you have reached a limit of API calls for your blah blah blah blah blah let me sign into better API to come and buy more credits because I I've done this a lot of times rehearsing this and I ran out of credits right I have now paid more API calls I made so many guy calls when testing this so we have some stuff here okay now it's 200 status country code ee alright nice where is hang on its rates that we're looking at so let me do forces as JSON instead it's Jason and then I'm going to see that data data dot rates what does that give us come on okay and then we have standard here let's see data rate standard see what it gives us okay web an object value 19 and so we just extract the value and then we have what we want okay so this is basically the call that we want our code to make alright so let me talk a little bit why we did this white play around and explore the API separately and because when I was a younger programmer I would I would just start writing code very fast I was a very very goal oriented and solution oriented and like I wanted to start writing code right away so I would just like start writing fetch right into order total here but over time I learned that this cost me too I had meant that I had to handle multiple problems in my head at the same time I had to event that I had to deal with the problem of figuring out the API and integrating the API into my existing logic as well and having to deal with those problems simultaneously tended to result in me making more mistakes and moving more slowly overall and this was especially true if on days when I was not at the top of my game I was tired or I was sad from something that happened in my personal life I ended up being a like my productivity ended up being very unreliable it sometimes work but sometimes I just got stuck and I produce code very slowly and and the the code that I produce was also more error-prone and after I saw this problem I I did something that improved me a lot as a program and that was starting to look for opportunities where there there's actually two problems or more baked into one big problem and looking for an opportunity perhaps we can break these problems out into smaller isolated problems and deal with them separately and one very concrete example that is what we're doing here would work what we did here is to get a little bit lovey dovey with an API first before using it in your code alright so let's go back to our tests in the series we are writing our unit tests first before we write the code and the reason why we do that is that I find at least that it is much easier to figure out what tests to write if you write the tests first whenever I try to write tests after I've written code I tend to struggle a lot to figure out what tests need to be written okay so test first we talked we've talked about why it's a good idea but I still have a problem with it because like how do you do how do you think in tests first because that then it's writing the test before the code feels like backwards thinking to me how do you get into the how do you make that not backwards thinking yes yeah exactly I feel that this writing test first is not what I am used to and therefore it makes me uncomfortable it's a new way for me to think and I I think I need some hand-holding on how to do this that is that those are excellent points i if you don't know I'm like I'm standing on this balance board it's like it's fantastic because it keeps me thinking clearly but it's also sometimes a little bit wobbly anyway the key is to instead or thinking in terms of what the computer execute is you think in terms of examples not what the computer executors think call examples so instead of thinking in terms of code of order total we're thinking in terms of examples of how to call order total and when you think about it that is in general a pretty good way of describing how something works a series of examples if you've ever read board game rules this becomes very obvious reading yes the rules without any examples it becomes very hard to parse because of that it's very common for good board game rules to have series of examples next to each rule set to explain like specific cases of how this rule could be applied and sometimes I even include entire game sessions so that you can get a sense of how the game works code at least to me yes it's very similar to that when a function is you know 10 or 30 lines long perhaps branch by a few if statements here and there then I find it hard to understand all the nuances of it if there are unit tests for that function showing a couple of test cases that makes it a lot easier for me to parse so these tests here you can think of them as examples showing how we how order total works or how we want order total to work when we're writing a test that doesn't have the code written for it yet so given that how can we change these tests you to take a step towards the code that we want well the first thing that comes to mind is that as we introduce fetch to this and a synchronous API call the order total is now going to become a synchronous it's going to return a promise so I think that is the first small step that we're going to do we can't avoid that so let's change all of these tests to expect a promise instead all right let's I know that this will break our test but nope let's verify that NPM test Bam Bam Bam Bam Bam four failed so let's go and fix or code so that this is this this becomes a synchronous returns a promise promise promise promise don't resolve strap this in puff by the way if you don't know if your promises not resolve is new to you all it does is that it takes a value and wraps that in a promise and if you're not familiar with promises in general you I made a video on promises here that you can check out this is also in the exo description let's run tests again and ham tests for past ice cream I know buddy see how we are working in really tiny steps we are solving one small problem at a time and this is very characteristic of unit testing you you go red green red green red green red green red green and for me this is very nice I really like this this is an absolutely favorite aspect of unit testing it provides me with a constant sense of progression it is a confirmation that I'm doing things things are going well and as we build a test suite it also gives me a sense of safety that we are making actual progress without breaking any of our previous test cases all right so now let's finally write a test an example that describes what it is that we want the code to be doing if stuff stuff stuff stops okay hmm but what is it that we actually want the code to do well we wanted to do quite a bit of things when you think about it we wanted to fetch data from that API calm and then we wanted to parse that response and then we wanted to to extract the the response they did take that response that parse response and extract the vast Pacific bath value from it and then we want that to what multiply the the toe or the total that we have calculated previously with that that VAT on a good day that feels that there's no problem at all perfect caffeine rush you I've had a great great week and I slept a lot but perhaps I'm also having a bad day that we're like this is oh good god where do I begin and those days are coding often feels a bit overwhelming you as tired and that's cases I find that it's really good to your sleep take a step back and ask myself what is the smallest possible step that I can take so perhaps it calls that API calm if country code specified so initially the tests we were gonna just focus on making sure that it actually calls that happier cone at all that that's what we're gonna do baby steps so I'm good to take this and just gonna grab this or the total here you know that cool and fine let's just change this to drag on waffles there's a really pricey perhaps I mean therefore we are only buying two and I'm going to write country here like and yes let's use Germany again here and and after the call has been completed we are going to do what are we going to do yeah this is where unit testing is really tricky to me you like how do we verify that something that hasn't that this is something is happening is happening inside of order total it's inside of it it's calling another function fashion how do we how can we inspect that and how can Blair well perhaps we don't have to perhaps we can just have it actually called the API in the unit test and then then just inspect with the results that came out just let's just use the real thing no no no we can't do that like if if we like the unit tests are supposed to run really really fast if we we have we'll have hundreds of these and they will run all over the place and if if we have all these Network calls in our test suite it will be very slow and we won't be able to run it on every same like we want to yes you're touching on one of the big benefits of mocks if we have mock mocks in place in our in our tests they will run me immediately and we'll be able to run hundreds of tests in just a couple of seconds which means that we will be able to test more and be more confident in our code also tests will be more reliable so we won't run into this where we just hit save and we just find that ok some network requests fail here or we have to run it again and just it yes it's gonna be nasty ok but even so how do we actually get at fetch how do we how do we mock it ok then perhaps the we there's a magic library or two that can kind of move over I'd require and allows us to inject it into the runtime no please not magic well some people do like that magic injecting thing and they use it like just has a no I know no I don't like that either right can we please use something that is it's clear and simple and that we can easily see how it works okay okay what about this what if we were the ones putting fetch in there oh you mean that we pass it in as an argument to the function here like like like this yes exactly and then we can then can do something like a fake fetch like pass that you know also fake fake fetch and that is just a function and it takes a rule and then we can just create a variable here like it's fake fetch cold equals false but then when fake fetch is cold we set that to Chu as fake fake fetch cold was true and then in the after after water total is executed we can do can expect is fake fetch cold to be true let's run that and TM test that should that means that this should fail and let's go into order total and then do assume that we need to pass in fetch here what's and we also know what if order dot country now I think that we will if we just do this it will be okay yeah now I know now this works the the test we created but all of these actually fail so let me fix that just quickly just gonna like em the function boom like that there and then I'm going to change the signature of all of these I'm gonna get an empty function because they don't really care about fetch these tests because they don't they don't use use it they don't use it so they don't have a country so they don't do the fetch and if we run this again boom all of them succeeds okay blow but a beer to come but we also want to make sure that it calls that API at home correctly right now it just calls idiot right now yes just like fetch it doesn't really call it let's see let's go back to the API call let's go back and check the or they are let's go back to the sandbox here here we have it I'm gonna copy that go back to the to the test and then I'm here but before setting is fake fetch cold we're actually going to you expect here we don't expect Earl to be due to do this you know what let's actually change this to another come yeah no okay cool let's run this this is also important that you actually check that your newly written test code is actually failing so that you actually make sure that it it actually test something otherwise it's very easy to just o write a test and then immediately jump ahead into writing the code and you that way you might just not actually test what you want so let's make sure that this actually calls the correct and the correct you are cool that's nice here we talked a little bit before like in previous episodes about triangulation versus fake it versus the obvious implementation and here I'm going to be content with the obvious implementation if we did triangulation we would write a test on one more test here to make sure that this was not accidentally duplicated between the tests but in this in this case I'm just going to write the the correct implementation which is order dot country let's run that test okay so what just happened here what we're doing is that we're creating this function here called fake fetch it takes an arrow and then we add an expectation here that the L should be right no this here and then take the country code that is the same as this one here everywhere and then it takes this variable sets this variable here is fake fetched call to true which we then after all they set it down we expect is fake fetch called to be true so we are testing if country code specified here but you know we we don't actually do that in this test so I'm going to remove that and I'm going to put that yes here to remind ourselves that we need to do that later and this is a way of creating pending tests I'm not providing a body so now when I run NPM tests it's going to show how one skipped so this is kind of like can use this as a kind of to do or in writing our test is very nice I know a lot of you will probably annoyed by the fact that I'm I'm not paying much attention to test naming yet but we will get to that later I'm yes at this point it's that's not what we're looking at and the way this all works is that we are passing this this fetch into order total as an argument so or the total does not require fetch here we don't do when a const fetch require note fetch we are we're not doing that we are getting that as an argument to this to this function and this is a technique called dependency injection it's very common to use in unit tested applications because it's a very simple way of of providing this and there's a lot to this I've made a separate episode about this you're going to see a lot of it in this in this series but if you're more interested in like specifically diving into dependency injection you can check out this episode here and this is also a episode in link in the episode description to that series if you're interested all that said I think that this episode is getting a little bit long here so we're going to end it right here like ooh cliffhanger next week we're going to proceed with implementing response parsing in this in this fetch API and we're also going to perhaps we're gonna fix this little thing here like that if country test specified like do a negative test maybe maybe you start looking at the specific mock function mock helpers that are in or ingest because this is just us creating a mock mock function here completely manually would vanilla JavaScript nuts we can do that you often do that but it's also nice to use the the jest helpers to make things a little bit more terse sometimes might get to that next time you have just watched an episode of fun fun function I release these every Monday morning Oh 800 G team if you're watching from the future you can check out next week's episode here and if you're watching from present time you can click here to subscribe so that you don't miss that episode if you're really forgetful you can also turn on notifications in I am nvj until next Monday morning stay tuned
Info
Channel: Fun Fun Function
Views: 62,159
Rating: 4.7902813 out of 5
Keywords: programming, coding, javascript, computer science, software engineering, software, functional programming
Id: 3PjdxjWK0F0
Channel Id: undefined
Length: 33min 7sec (1987 seconds)
Published: Mon Dec 04 2017
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.