GoLang Unit Testing and Mock Testing Tutorial

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey what's going on my name is james from nerd academy and in this video we're going to go over unit testing to go so let's go so you might be wondering why do we care about testing our code we ran it and it worked so we tested it right well yes but actually no the purpose of testing our code is to ensure correctness and it runs as intended plus finding any unforeseen bugs or edge cases that may make it not work correctly and one way of doing that is something called unit testing a unit could be an entire module or just a function or an object oriented programming an entire class we try to isolate those units as much as possible from the rest of the working code and then you could build up to more extensive and complex testing such as systems testing testing may not work with units being isolated so we create something called like mock objects and test dubs these stubs and mocks are used to simulate more complex parts of your software that are either impractical or impossible to incorporate into your unit tests or they're slow or they rely on an external dependency example of this is getting all the posts from your database you can create a mock or stub to basically just return fake data instead of going and getting that data from a database it's better for your tests to run quickly instead of relying on network to conduct those tests so you'd create a mock object to kind of just return dummy data and then you can test edge cases and all your other stuff that way testing is often overlooked and is given minimal amount of time until the deadline is looming okay not always but i've seen it enough testing is important that's why there's a whole methodology called test driven development test driven development usually starts with the spec and then you create your unit test or testing from that and then you write your your software to pass those tests but we're focusing on unit testing so let's hop over into our code editor and take a closer look alright so i went ahead and created some very nonsensical kind of libraries if you will so we have a math package that's going to add subtract divide and multiply then we have a server which is going to go get the weather from somewhere so we have the get weather method it's going to take in this url where the location is and it's going to return this weather struct object and an error so let's go and start and creating our unit testing for our math library so i'm just going to create a math test here math underscore test.go package math so as you can see code here already said hey run package tests or run file tests like i can click that and it'll try to run those things so go to get the test to run i'll get to the command line in a minute but to get it to run properly you have to have math underscore test and then also our math functions have to be named a certain way and that is starting with a capital t for tests and then usually the method name you're testing in our case we're going to start with add as you can see we got a little compiler warning here we need to add the testing t object so testing.t and i didn't import that so it's given an error so quick fix import testing there we go so this is the function signature if you don't want a function signature it's going to be a method name any parameters and a return type that's what constitutes a method signature so to do a simple test we can do we call the method we're going to call add we're in the same package so we don't have to call math.add we're going to pass in one and two so what we do is check the result if result does not equal four then we have an error so we want to use our little testing let's make this lowercase t i made that capital so we go t error i'm going to use error f for format let's say add 1 3 failed we expected percent d and then we got percent d so we're gonna pass in we expected four and we got result instead else let's go ahead and put a pass in here t dot log f so we're gonna say add one three passed we expected percent d and we got percent d and then we'll pass those in for and result okay gotta go into our math folder and what we do is go test that's all we gotta run so it's gonna find underscore test.go file then it's gonna find any method to start with a capital t test and your method name and then run the test so there you go it says pass great but there's a little bit more information we can get we can do go test dash v for verbose that's going to tell us the output that we literally just put in there and then we can also do let me reset this so it's up higher we do go test we'll see verbose and cover so what the cover flag does it adds a coverage so out of our tests we've only done 25 of the coverage of all our code so if we go back to our math.go here all we've tested was add and we didn't test subtract or divide or multiply now the purpose of testing is to find your errors so in your code so let's go ahead and test our scroll this up here let's go test our divide function because as it's written now there will be an error if we if someone passes a certain value to it test divide pointer to our testing.t object so as before we'll do results we'll set that equal to divide and we're going to divide 5 by zero so let's see what happens if we try to divide by zero so if results does not equal zero because we would like to do that instead if we divided by zero then we'll just return zero from this method so let's see what happens t dot error format divide five by zero failed expected percent d got percent d yeah we are returning a float 64 from divide so i'll use that instead the percent f instead of percent d so we expect zero and we got results okay i'll put zero to zero because it doesn't like me just putting zero i think it's just a straight up integer let's put that aside so we can get more room there else we pass so that means hey guess what it returns zero great oop we need log format divide five by zero passed we expected percent f got percent f go and toss the new line in there 0.0 and result so now if we try to run this again as is clean that up let's do the test verbose and cover uh-oh then like that you know divide by zero so it actually failed out the whole thing because we're not supposed to divide by zero so now we know we actually have an error so you could handle this two ways i showed doing zero so if we did that we'd go if if y equals zero then let's just return 0.0 or float 64 54 64 634 zero oh okay so you can handle this way or you could catch that error and say if zero is if y is equal to zero then just return an error instead but you'd have to return you'd have to change the method method signature so tomato tomato either way you want to do it is fine all right so let's test that again there we go so both tests pass but we're still only 50 but these are very kind of just trivial things to test really so all right so we're done with the math for now let's go over and try to we're not done with math hold on math is never done we're never done with math instead of just kind of testing one at a time we can like create a a slice and test a whole bunch because that's what you really want to do so let's create a type of a struct we'll say add data we'll test the add that's fine instruct and then we'll have and we'll have inputs it'll be uh a slice of ins and then we'll have result that we expect from those two those inputs you could have a yeah let's do this this way we'll have x and y instead of inputs of a slice there's no really no need so let's kind of comment this stuff out so that's the way you could do it if you just want to do do it that way you could but we'll use a slice so i'll call this test data create a slice of the test data oop add data i'm sorry and then we'll just create a few let's say one and two and we expect three how about three and five we should get eight right and so on and so forth so we'll just add one more here so seven and negative four should give us three we'll do a simple four range loop so four underscore datum is range test data and we'll do results we'll set that equal to the add of datum x datum y and we'll check if results much like we did before if result is not equal to datum dot result because that's the result we should get well we're going to do what we did before t error format say add with add percent d and percent d failed the expected percent d got present d and then we just need to fill in all those values in there so we're going to put in datum item x datum y and datum results result okay now let's run our test again and see what we get there you go all of them passed so that's a good thing all right let's head over to our server package instead we're done with math for now and let's create our server test.go package server all right we're going to like we did before we're going to create a struct to kind of hold our kind of test data we're going to do a little bit differently because go has a http test kind of like mock server that we could use that goes on our loopback interface so we can have a server running that our method will go and try to reach since we're adding since we have a url a parameter we could pass it our own loopback so it's gonna try to go and get our own test data i think you might understand once we get going here so let's create that struct now so we're gonna have a type we'll call this tests it'll be a struct and i'll put in this now when we get to actually looping through and doing this stuff we need the name of the test you'll see later so we'll have a name then we need a server we'll call this server we'll have the http test dot server yep we need to import that we got a few things to import so it's under the net http http test then we're going to get a response we're going to write our own response because we're going to do a mock response and that will be a pointer to our weather object and then we'll say expected error and that'll be an error because regardless of situation whatever happens it's going to return either nil and an error or this can return our weather object and some kind of error so we're gonna test if we get the weather object in nil then we can also test if we get nil for a weather object and then an expected error all right so let's go over to our test our server here it's like we did before we're to do the same thing we're going to do a funk test get weather we need our testing object again all right so it gets a little tricky but it'll be fine so we'll create our tests in a slice just like we did before but we're going to do it kind of very basic just for brevity so tests we'll set that equal to a slice of tests and then we'll create our object here so our name will be basic request and the server we'll set that to http test dot new server we have we need the http dot func handler handler func i'm sorry and then we got to pass in our response reader and our response object we have our this is going to be our method that we're going to use to respond with a request that we come up with first but what are we missing what's going on here oh my bad we need to wrap this in an anonymous function nope we're going to take that back and put another one there we're in a slice there we go response see if i can spell oh my goodness what's going on here request there we go so if we we could go in here and do a right header http status okay and then this is where you would return data so if you wanted to do some edge cases where it returns something maybe could happen but we'll just return good data this time right here so we're gonna write it's a byte slice and then we're gonna have oop we need the backticks and then little brackets for json data so our struct was a city say denver colorado and the weather we'll set that equal to sunny not too exciting but you get the idea yep all we had was a city oh forecast my bed the forecast is sunny okay now we need to have we need to put it in our struct here a response that we expect to get set that's a weather object we need to get the address weather and we'll say city is should be denver colorado and the forecast we expect to be sunny then we need to set our expected error which in our case should be nil so that was just a little complicated so let's go through kind of what we're doing here we created a struct called tests we have the name we'll get to that in a minute we have a server which will be in our case an http test server so it will spin up and run and kind of listen listen for a get request and then it will return this response right here this weather object which we did we created in json since our server our weather struct here is written to accept json and it will decode here then we kind of created an expected response field and then an expected error so this is a way to mock going out and getting data from the net instead we just do it all locally and it'll be pretty quick all right so at this point you could add a whole bunch more tests that if you want to test for errors or any other edge cases but you basically have to copy and do the same thing again but you would want a different name and you'd want to have something else here inside your http test new server this is where you could add a whole bunch of tests but we're going to keep it very simple just for brevity because this one's already running pretty long so like we did in the math the ad we're going to do a range four we're going to loop through our tests our test slice and then we're going to run our tests so before we kind of just did our we called the method ourself and then we check the results we do something very similar we're gonna do t dot run so it kind of just does it in parallel in a way so we can do something like set up a server and run that we need the name so we have test dot name and then we need to pass the method which in our case is func testing [Music] dot t now this is where we run our test so we need to defer our test server to close we need to defer that so it doesn't close right away we're going to get a response and an error from our get weather method we're going to have our test server url which should just be our loopback interface that our server right here will be listening on in parallel or in a co go routine get our weather from there and it's gonna return whatever we put in here so we're also gonna use a little something fancy called reflect don't get too too worried about it we're gonna do a deep equal you can check x and y if they're equal but when you do something like slices or structs and all these other kind of more complex data structures you need to deep check as you can see here the deep will check if they're deeply equal it'll check all the you know the values and all this stuff from the array and all the structs if they're like in a struct the values are deeply equal with their corresponding fields are both exported and exported and all that stuff so it's making sure that they're the same so we expect our response and our test dot response to be deeply equal in this case they're not deeply equal so we'll go t dot error f format failed expected we're going to do percent v for a value so we can pass in a json object and it'll just kind of print it out for us but we got percent v again so we expected our response loop test.response and we got the response now we can check if the error we're going to use the errors package so this is basically is going to check if the errors are equal so if our error and our test.expected error if they're not equal then we have an issue so let's do t error f again say failed get a little bit more verbose here uh expected error failed expected percent v we got percent v so let's go we expected test.expected error and we got error all right let's go ahead and run this test and see what we get so go test dash v all right passed so you can get a lot more complex with this and see what happens if you get a 500 some kind of 500 server error or you know you get a not authenticated let's say you had some kind of authentication that you had to pass up in a json web token or something so you can get pretty crazy with this and frankly it's sometimes needed to make sure your software runs properly all right well that was the basics of unit testing and a little taste of mocking in go so if you've got anything on this video do me a favor hit that like button and if you watched this far on the video i thank you so much i really appreciate it and if you're not subscribed go ahead and do so and if you want to watch more about golang just watch this video right here and we'll see you in the next one [Music] you
Info
Channel: NerdCademy
Views: 398
Rating: undefined out of 5
Keywords: go mock testing, go mock testing tutorial, go programming, go programming language, go programming tutorial, go tutorial, go unit testing, go unit testing tutorial, golang httptest, golang mock testing, golang mock testing tutorial, golang programming, golang programming tutorial, golang tutorial, golang tutorials, golang unit testing, golang unit testing tutorial, programming, programming tutorial, software developer, software development, software development tutorial
Id: XQzTUa9LPU8
Channel Id: undefined
Length: 18min 45sec (1125 seconds)
Published: Mon Dec 06 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.