Learn Unit Test with .Net 6 with xUnit and MOQ

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello friends thank you for watching this video i am muhammad and today we are going to be discussing unit tasks with dotnet 6. we're going to start very simple by adding a unit test library to our console application and then try to create some tests to test the application functionality once that is done we're gonna jump into something which is more a bit complicated which can require dependency injection and then we're gonna see how we can actually utilize the mock library in order for us to get there if you like this video please like share and subscribe it will really help the channel so let's jump into it we're going to start by discussing unit test with xunet and mock in asp.net core 6. so let's see what's on the agenda for today first we're going to be discussing what is a unit test and then why do we need it then we're going to be jumping deep into the frameworks of unit tests once that is done we're going to be discussing how can we think about unit tests and how can we approach them then we're going to be discussing some of the ingredients that we're going to be needing in order for us to do the unit test and then we're going to be jumping into the coding so what is a unit test a unit test we can think about is the smallest piece of code that we currently have that we can test we can think about them as the functions that we currently have so for example let's say we have a controller and inside that controller we are adding editing deleting and viewing all of the employees every single piece of this controller is a function and every single function can be tested separately and every single function is completely isolated from the other one so for example once we are calling the view all just all that function is going to run in a complete isolation so we can test that by itself if let's say we're trying to update a user or an employee that's also going to run complete isolation if we're trying to create or add a new employee that's going to be around isolation so unit tests basically are functions or a separate piece of code that only run together in complete isolation of the rest of the code and basically within this we can actually execute some testing against this isolated piece of code in order for us to get the results so in summary that's why the unit test we're trying to test a single unit of piece of code or a single piece of isolated code so why do we use unit test first thing is save time by actually writing a lot of other automated tests we're actually saving a lot of time by doing all of the manual tests that the usual q8 needs to do so by having all of this test treating once and make sure that they are on an automation we are actually saving a lot of human hours in order for us to do all of those manual tests which the usually the qa people do so first thing is the automation that we can actually get by saving time second actually it's the opposite by running all of these tasks we're saving a lot of time second of all is when it comes to automating testing we can have a lot of much more detailed scenarios and much more in specific scenarios that we want to test specifically if we're dealing with such a big enterprise solutions or for example with a lot of complex financial data a lot of these testing needs to be done up to the point and up to the digit that we are trying to accomplish with these functionalities so that's why unit tests uh are much more faster for for running these tasks because basically once we automate them and we can automate these advanced uh testing scenarios we can get the results asap as soon as these test runs as well on top of all of that in case anything directly breaks what when we change any part of our code we can directly recognize it when the unit when we're trying to run unit tests from the developer point of view so for example let's say a developer change something on their machine related to a specific piece of code and they run the task for it and it fails it can act they can actually directly recognize where this when it fails how can they fix it and actually investigate the issue if we're going to wait for manual testing so let's say for example a developer does any of the work and for example it does his own testing or her own testing once it actually goes to qa and then the queen goes to the testing process from a to that and they have to do everything one two three four in order for them to get the specific case that's where you can see that the time is going to be consumed in order for us to get to that point while on the other hand if there was unit tests from the get go where it's actually covered all of the detailed scenario that we currently have we would have saved all of this roundabout trip and the developer will be able to fix the scenario right there and there so that's the first point saving time the second point is automation as we have said before when it comes to saving time automation is a very powerful tool so for example if we have like thousands upon thousands of tasks covering those details our this enterprise application that we currently have running those automation we can either run overnight we can either running for example on a scheduled task we can either running on demand all of this automation is really really powerful for us because basically once those automation are running in the background the developer can do any other work that they need to be doing in order for them to move forward with the job or for the task that they are trying to do and whilst does automated testing are running in the background if there's any issues then developer will be actually notified so we can see here that the feedback loop which is really important that automation and unit tests provide us is really good for the life cycle of the product as well as the quality of the code that the developer is actually producing the third point is efficiency and this is really important because in order for us to apply unit testing our code needs to be of a center certain standards for example it needs to have all of the solid principle already integrated inside that code so we are actually allowed to have dependency injection which will allow us to mock certain services so on so forth so that by itself it will give us a very structured and very rigid code uh source code that we can actually utilize and expand upon so all of that unit testing is going to be able to provide us that out of the box because if one implement unit test we need to implement the solid coding principles in order for us to actually test it in a unit test way as well with unit tasks we are making sure that we are covering all of the potential troublesome scenarios specifically when dealing for example with financial data with a difficult transaction a high speed or high high throughput scenarios all of those unit us will be able to actually give us the information that we need and making sure that we are covering all of the aspects of course there is no 100 percent um certainty that we're going to be able to get this product back free but at least unit testing will be able to give us at least 99.99 that we are almost getting there there's always going to be some certain scenario that we might not think of we only might discover them later on down the road when the application goes into production which is not recommended at all but at least once we are covering all of these we are able to at least know from the beginning if something going wrong where is it how can we fix it and how fast we can put a fix in order for us to get it up and running the first point of what we need unit test is documentation because basically once you are trying to write unit tests we in a way we are actually documenting the functionality of our application because if we would if we think about it when we're writing unit tests we're not just writing a test making sure that the input is valid or just we're making sure that the outcome is a fair certain format that's not the case what when we're trying to build a unit test what we're trying to do is we can actually trying to build a client of that application for example let's say we are trying uh right to write a unit test for our api the unit tests are basically the first client that this api that's going to be consuming that api and basically once we think about it that way we are actually documenting all of the processes and all of the functionality that this api has and in a way we can actually have a certain type of documentation that will allow us to understand what this api is doing and what are the critical point of this api that we need to pay really attention to the fifth point here is going to be code quality because if we think about it if we are already applying the solid principle we are applying proper dependency injection we are applying unit tests our code equality is going to be much more higher than if we're not doing that and that means that maintenance of the code is going to be way more easier expandability of the code is going to be way more easier trying to add more functionality is going to be more way more easier because we already have a strong code base and have a strong source code that we can actually utilize on the long run the last point is it's going to make our code reliable why because if we have those unit tests running in an automated way for example every night making sure that we are getting 100 percent of our tasks correct there's no single failure it make us know that it will allow us to know that all of the changes we have introduced to the source code did not affect the current functionality and it means that when any consumer is trying to consume our application they're going to have the same results as before and that should give us a bit of a peace of mind that our code is reliable and the source code that we are putting out and the application that we are actually uh giving it to the public is actually executing as it should be and in case any of our changes has affected the existing behavior of our application the unit test will fail because that we can see here the direct interconnectivity between our application the source code with us and the unit test so it makes us protected from all of the from failure or potential failure when it goes to production when it comes to frameworks inside afsp.net core there's mainly three framework that we can actually utilize the first one is amistast which is the oldest framework that currently exists ms test is very reliable but it's also very slow that's why i don't really recommend utilizing amazon the second one is an unit and an unit is has a lot of features baked in into it is much more faster than i must test as well it's much more stable than i must test and the other one and the last one is going to be ax unit again action is very fast it has a lot of functionality and it's very reliable for this demo today we're going to be focusing on ax units so how should we think about testing well in essence when it comes to thinking about testing we need to think about it as a consumer of the api so for let's say for example we have an application that takes for example registration from a form and we have an api endpoint that we want to test so in order for us to think about that we can for example create test if the valid of a string is equal to certain length if for example these are all valid dust or for example if a mobile number of a certain length that's all the valuable tests but when it comes to actually thinking about it we need to think about it in a way that we are how a consumer would actually utilize it of how our uh api consumer we're gonna be uh consuming actually this api we need to think about it of a way that we either wanna utilize this api we don't wanna go to the nitty gritty uh of adding our writing test for every single aspect of our piece of code or i said piece of word that we have we need to find the right combination of time as well as code coverage and this filing this right balance and finding this right equivalence of the of basically time and code coverage is going to be the key structure because if you want to write tests you can spend weeks upon weeks upon weeks on writing unit tests for a certain controller but that's not what we want we want basically for us to cover the main aspects or going to be the most challenging aspect of our controllers the most complicated parts that for example certain client-side validation will not be able to do certain api side validation will not be able to do these stuff that we're now we need to actually write unit tests for the complicated business scenarios and the completed for example calculations that we currently have that we need to do the unit test for it's not going to be only about uh writing like a validation about the length string or a valid phone number or valid email again those are actually valid unit tests but it's all it's going to be up to the developer and after the business needs of the level of the code coverage that you want the test to do as well on top of all of that you need to think about it in a way how you want to utilize it as a consumer how are you trying to approach that api how are you trying to actually utilize that api not actually going line by line inside our controller or outside our action our function to write unit tests for every single line you can do that but again it's all about the balance between code coverage as well as the time that we want to actually utilize utilizing on the first order unit test so what are the agreements that we're going to be needing first we need to have visual studio code because that's going to be our code editor as well we're going to be needing the dotnet 6 sdk you can find the links in the description down below or on the screen right now so the first thing that we need to do is we need to make sure that the sdk is installed successfully in order for us to do that what we need to do is we need to run the dot net dash version command in order for us to check the command the sdk version on our machine so how do we do that inside our terminal we write dot nut dash dash version and we should see here the version of our sdk and in this case i have version 6.0.101 which is the latest version of the not 6 sdk by the time of this recording so once we have done that the next step for us is actually we need to create our application and we're going to start from there so here what we're going to be doing is we're going to be creating a console application and we're going to be adding all of the stuff to that console application so it's going to be not new console we'll give it a name and we can call it for example let's call it testing dusting up and we create this console application perfect so now let's open our application in visual studio code now that we have opened our application visual studio code the first thing we need to do is open our command line so go to terminal new terminal and we'll have our terminal here so the first thing we need to do is we need to go to our application and then we're gonna run the nut build to make sure that the application is building as it should be once that is done the next step is we need to install some new packages and these nuget packages are basically the unit packs the unit test packages that we're going to be utilizing so the first new that package is going to be the microsoft testing sdk so it's going to be not add package microsoft microsoft dot net dot test dot sdk that's the first one and this should take a few seconds to be completed perfect the second one is going to be x unit so it's going to be not add package x unit also this can take a few seconds perfect the third one is going to be not let's remove this it's going to be not add package axe unit dot runner dot visual studio also another few seconds that needs to okay perfect and the last one is going to be not add package cover a lot dot collector perfect so once this package has been installed what we can do is we can go to overseas brush file and we can make sure that everything is stored there so first we have the nut sdk action x unit as well as the cover lot collector great let's build our application to make sure it's running successfully so dot nut build great so now that we have actually created our application and we have added all of the nuget packages that we need to do the next step for us is we're going to be creating a small user management functionality it's going to be very basic uh something that we can actually write unit test against so inside our application here we're going to create a new folder and we're just going to call it functionality any random name will do but for now we're just calling it like that we're going to create a new class and inside this new class we're gonna call it uh user functionality actually we can call it user management because we're trying to move into user management manage okay great so once we have created this file the first thing we need to do is add the namespace and this is because this is not six we can just add a semicolon at the end of it so it's gonna be uh what's the name of the application that we said it's gonna be okay so this is the first wrong thing that we did we added in the wrong folder so let's delete this and let's do that again so this needs to be inside our testing app so here we add a new folder we'll call it functionality uh inside this functionality folder we create a new class and we'll call this class user management and the first thing we need to do with that is just like take the standard of the nutsex and make it the way that not not six likes it which is like this once we have done that right now what we need to do is again because we are utilizing.6 and actually after that c sharp nine let uh c sharp 10 sorry because we are using c-sharp done where the function that we're going to be using is it was introduced in c sharp 9 which is records this would make it much more easier for us than creating classes so it's going to be public record we're going to call this record user and basically it's going to have a string of a first name and a string of a last name the next step is we're gonna be actually adding properties to it which is gonna be end of type id and then we're gonna be adding the date time so prop date time i'm gonna call it createddate and we're gonna give it the default value of datetime dot utc now and then once that's done we're going to add the phone number and the last one is going to be the verified email so property it's going to be boolean and it's going to be verify verified excuse me verified email and we're going to give it the default value of false just to be on the safe side okay so that's the record that we're gonna that we're having the next step is we're gonna actually start implementing our user management class so the first thing first is we need to basically because this is currently right now is gonna be a console application we don't wanna go into the entire process of actually creating a database and actually try to create adb contacts and we're going to actually connect it and have all of that so on and so forth so for the sake of this demo right now we're going to be creating an in-memory database and that in memory database is going to contain a list of users and we're going to take it from the from there so again this is going to be an in-memory database for the rest of the video everything we're going to be doing is going to be in memory in the next one we're going to actually see how we can connect our database and create the test from there so how can we create an in-memory database it's going to be very easy so we're going to put private read only we're going to make a list of users we're gonna call them users and basically they're gonna be again all of these functionality and the way we identify as part of c-sharp done we can actually directly utilize them so this replace equal the new list of user parentheses great once we have done that the next step for us is we need to create because it's an in-memory database we need to create a counter for the id so it will automatically increment so in case we are adding more users so for that we're gonna have a private and we're just gonna call it id counter simple as that kind of give it an id one to start with and then we can add another to it so once we have done that now we need gonna add a couple of methods and these methods basically they're gonna be able to return to us all of the information that we need from this class so first one is going to be public and we're going to allow us to get all of the list of users that currently exist so it's going to be public i innumerable of type user and basically we're going to call it all users and basically it's going to give us the list as simple as that so that's the first thing the second thing is going to be adding users so public void it's going to take a user and basically what it's going to be doing is going to be adding it to the list so it's going to be underscore users dot add user and basically what we need to do is we need to automatically manually sorry increment the id for it so the way we do that is we're gonna put with actually here with id equal id counter plus plus so that's what's going to be doing is it's going to take the user as that we have it's going to take the first name last name and then for the id we're going to be automatically auto incrementing it and the rest of phone number is going to be empty daytime it's going to be automatically set and verified email is gonna be automatically set great once we have done that we're gonna add another functionality which is gonna be update phone number and basically what we're gonna take is public void update phone user user just going to take the same user and we can utilize from there and all we're going to be doing right now is we're going to be connecting not connecting we're going to take this in-memory database look for that user with the same id and then just update the phone number so it's gonna be via adb user for now we're gonna call it underscore users dot first and we're gonna pass the condition where x dot id equal equal user.id and then once we have that we're gonna put dbuser.phone equal user.phone as simple as that so once we have done that we're gonna do the same thing for the email it's gonna be same logic but instead update phone it's gonna be verify email and actually we instead of having passing the id we can make it as an integer here i'll put here user id and we can pass this like this and verified email is going to be true simple simple like that and after we do all of that i think that's more than enough for a demo functionality for our application right now so let's save this once we save this what we're going to be doing right now is the we need to actually start unit testing so how are we going to be starting unit testing there's a couple of ways we can do that the first one is we can actually write our unit test inside our main console application and try to add them from there that's a good approach but if we're gonna try to like stick to a certain standard it's better to always create a separate console application that's actually gonna be testing sorry a separate class library application that's going to be testing our console application so that's where what we're going to be doing right now we're going to actually create a console class library and that class library the main job for it is going to be actually to test our console application so let's do this right now so first thing first let's check where we are here so we are inside the pwd pwd inside our testing app we're gonna go one uh folder behind and here we can actually create the new application so it's gonna be not new and because we are testing we cannot just create any normal class library we need to create an x unit library so it's going to be x unit on and basically what we can do here we can put testing what did we call the application testing app test it's always to have the test added to it in order for us that no it's a test so once we create this just take a few seconds and we can see here that the application has been created for us so let's open it here and we can see how application here very simple very easy uh we here we have our first test we don't need it let's delete it and then we create our own test delete yes thank you very much so once we have deleted it the first thing we need to do is we need to add reference between this a new class library and our application how we do we do that we just utilize the not add so that not add testing app this thing up that's yours approach reference to testing up the test testing out the test and now click on enter we can see uh i think it's going to be the opposite oh yeah it's going to be the opposite apologies for this yeah this shouldn't be it's the opposite way so i'll just delete this save it actually that i think about it we have added this here in case we wanted to add that was the original plan if you want to add the same test inside our main console application but we don't want this right now so all this we don't really need at this moment so we can remove them yeah let's remove them and let's add the reference that we wanted to add so we're gonna put let's remove this so it's not going to be test so i'm going to be test here's going to be dust dot test and here's going to be the test let's run it reference add completed so if we open this we should see a reference to it perfect exactly one that i wanted great so once we have added those what we're gonna do is we're gonna add a new class and this class we're going to call it user management testing name based on the class that we want to test user management testing great so once we have done that the next step for us is we want to actually start writing our test and the with the way that we said before is we wanna when we wanna actually test our code and we wanna actually execute test we wanna think about it when we're writing our tests as if we are a consumer of that functionality or a consumer of that api of that endpoint so on and so forth so we want to think about it from of a way that we are actually consuming it so that's what we're going to be doing right now so the first thing we want to do is we're going to actually first add the test so how do we do that well first we need to decorate any method that we create by this attribute facts so when we add the fact mean we are telling it that this is going to be like the first unit test that we want to run or that's the unit not the first that's the unit test that we want to run after that it's going to be a normal function public void and then we're going to give it a name so because we're going to add first the functionality inside user management here the add functionality that's the first thing we want to add test so we're going to put void and we're going to put add and we're going to call it add user or create user so that's the first one we want to add we're at us we're giving it any random name but once we have we see that name we need to make understand what is the what's going on and that's part of the documentation that we spoke of so once we have done that we can actually right now uh first let us add those references here using x unit and now we need to actually write our test so how do we write uh how do we start writing our tests so writing a test is consumed of three parts first is going to be arranged then act then assert so what does a range act assert mean so a range means that we're going to actually point it out to the exact function or method that we want to test that's the first thing then act is actually we're gonna actually execute what we want so let's say we want to add a user we want to execute adding a user and then once we execute we're gonna get a response and then we're gonna utilize that response in the third phase which is the last one which is basically we're going to compare what we currently have with the expected results and this uh comparison is actually what's going to make the test succeed or fail so let's do that again so as we can see here we have three sections we have the arrange which we're basically setting up our test to connect to the right part of the code that we want to test second is we're going to execute that code in order for us to get a response and then third is going to be the assertion which is going to be actually combining or not considering not combining we're going to be comparing the outcome of the execution with the expected outcome that we wanna that we that is the actual outcome that needs to be out and once we compare these two if they are equal for example or they are the same number so on and so forth that has passed if there's any difference between them it's going to fail so let's do this right now so the first thing first because basically what we did here is going to be a simple class you can actually just initialize it and that's what we're going to be doing right now so it's going to be var user management equal new user management without the tasks and we're gonna have to fix the references so let's do this right now okay great so once we have done that the next step for us is we actually wanna actually add the user which is the action that we wanna do so inside our act we're gonna put user management dot add and we're going to add a new record inside of it and basically we're going to put the new and we're going gonna pass the first name it's gonna be muhammad and we're gonna pass the last name and basically we are passing the record information that we have as simple as that so once we have done that the next step for us is we need to actually assert it means that we need to actually test if that addition has been successful and the information that we are actually added success or not again this is all an in-memory database so it should be fairly easy for us to do so first we're going to put for we're going to get the result that we saved save user we're going to say equal we're going to check by assert dot single and we're gonna put user management dot all user so what does that mean it means that because right now it's an emergency base and it's empty so we only have one and we are asserting that we have only one single user basically getting the first one inside of that so once we have done that the first thing we need to do is assert dot not null but actually yeah not null let's start with that and we're gonna put saved user so basically what we are here checking that the user management list is not empty that's the first thing the second test that we want to do is assert dot equal what does that mean we want to actually make sure that the value that we have saved inside the save user is actually the one that we have currently saved so first we're going to say what is the expected value so that my first name is to be muhammad and the last name is to be saved user dot first name so we need to make sure that these two match then we're gonna put assert dot equal as well for my last name so it's to be la wand uh it's going to be saved user dot last name so now that we have asserted basically that the actual value is not null and the actual information that we have saved first name and last name are actually equal which is great then what we're going to be doing is we need to make sure that the email validation is false because this email validation has been added by uh by our record directly so let's do this now so we're going to be assert dot and as we can see here we have a lot of options that we can actually utilize to assert certain information a lot of option and it's this is going to make our life way more easier so right now because we're checking our booleans what you can do is we can put false and we need to make sure to pass the right value so saved user save saved user dot verified email so because this is out of the box needs to be false so this should pass here so let's uh do a quick recap we have one we have created our uh class and then the first thing we did inside this class we created we added the decorator fact which means there can be a unit test and then we started creating our function which is the unit test itself and it's separated into three we said the arrange the act assert the ranges we're going to be i specifying the piece of code that we want to test act is actually executing that code and basically assert we need to actually verify the outcome of that code make sure it actually give us the expected outcome so now how do we test it you might think to yourself so the first thing we need to do is we need to navigate to that library so as we said it's testing the test and lastly navigate dotnet made it really really easy for us and we have basically a command from the command line that we can actually execute in order for us to get the answer that we want and that command is going to be not just as simple as that so inside the terminal what we need to do is we need to write dot nut test we need to wait for it a few seconds for it to start to build the application first and then it's going to start running and we can see here application has built and then we got the result that we wanted and we can see here that we say we have the past which is great and we basically give us a quick summary of our test so we have zero test failed which is perfect we have one test because which is pass this is the highest that we have and then we have zero tests script and we have see basically the duration of what it took for us to execute this great so the second uh function that we're gonna be adding right now is for us to check the update mobile function if it actually works or not so how are we going to be doing that again if you want to write an unit test the first thing we need to do is write a fact so we can say it's a unit test then we put the public and then we're going to put a void because it's not returning anything and we're going to put here update and we're just going to put update what basically we're going to put update mobile number it's not going to take anything and basically we're going to have to do the same three pieces again so as we said before the first one is going to be a range then it's going to be act and then finally it's going to be assert the three the triple a's okay so we can utilize the same thing as here so let's copy this and this because basically it's the same information that we currently have so let's copy this okay great so once we have put the arrange and the act the next step for us is to actually uh we need to build on the act and actually update our mobile number so we're going to put user management or actually yeah let's get first the user management the user so we're going to put far first user equal user management dot all users dot to list dot first just has to do this but first and let us at system.link i think yes system.link and that should work perfect and now once we have done that we're going to update it so first first user.mobile number phone number yeah that's fun we're just gonna put that let's give it for example plus four four this number for example and that should be it and once we have done that what we need to do is we need to update the phone so we're going to put user management dot update phone and we're going to pass first user so basically what we did here is we added a user and then we got the user we have updated their phone number and then we sent it back uh to the method that we currently have called update user for us to update the phone now we need to assert now the fun part starts so how are we going to assert so first thing first we need to get that same thing as we hear we need to get the first user so let's copy this and we'll put it here so for our saved user a third single and then we're getting that user and first of all we need to check assert dot not null so we want to make sure that it's not empty and we're gonna put saved user and then once we have done that we want to check the value so we can put assert dot equal and then we're gonna pass the mobile number that we have added let's copy this and let's here pass the mobile number it's going to be user saved user sorry dot phone and that should be it okay great so let's save this and now let's run our tests and now we should see two of two perfect so we have green which is passed and we have two of two which means that all of our test has passed excuse me so now that mean that our first part of the testing has been completed and basically right now we have covered a simple actually simple methods of actually writing some functionality a very basic functionality creating an excellent application application or a console library connecting it to the main console application by the reference that we have added and then we have write in written two tests and we have introduced the three part which is going to be first of all it's going to be a range act and assert as we said before a range is actually just arranging the data act is actually implementing the act that we want to do adding updating deleting so on so forth and assert making sure that the outcome of the act is the expected outcome that we have so that's the first part the second part right now that we're going to be delving into which is going to be more of how we can actually utilize unit tests with dependency injection and basically with interfaces as a first step okay so let's get into it right now now that we have covered the first part now we're starting to start with the second part with the injection sorry interface injection and basically in this part we're going to be utilizing the mock library but first we're going to try to do everything manually and see and then we can we're going to introduce the mock library and see how that library is able to help us first by saving out of time and reducing a lot of the error prone code that we might have introduced in order for us to write unit test okay so let's start first thing first what we need to do is we need to add a new functionality inside our functionality folder so inside the functionality folder right click new class and this is new class basically what we're gonna call it the shopping cart and basically the functionality that we're trying to create here is we're gonna try to make a shopping cart basically adding stuff to it moving stop to it something like that very simple implementation the main uh thought behind this is we're gonna try to do some construction injection into the to our shopping cart and then we're gonna see how we can actually mimic constructor introduction inside our unit test so we're going to call this shopping cart and if we open our functionality we should see it's not there let's try again the new class shopping cart again let's try it's not adding for some reason let us add a new file we'll call it shoppingcar.css and basically it's going to be similar to here so let's take the same namespace and let's put it here and then what we can do is we can just create a public class and we'll call it shopping cart and we'll take it from there so now we have basically a class called shopping cart inside our functionality folder the first thing first is we're gonna actually try to create an interface and that interface is going to try to represent a library and from there on once we have that interface and we have that library we're going to inject that interface excuse me we're going to create an interface which is going to represent a database or what i mean by database here it can be a database library it can be a direct db connection it could be a data context for a database anything we want for now we're just trying to mimic a database so we're going to create that interface first which basically represent adb contacts or a database for us and then we're going to inject this interface inside the constructor of our shopping cart to implement that we are trying to do a uh injection of an interface for us to save stuff to our database this is all uh for demo purposes okay so first thing first is let us create this interface and basically it's gonna be public interface and we're going to call it i a db service just to try to mimic a database service and basically inside this idv service we're going to have to method awesome save item to shopping cart and we're gonna pass the product we integrate the product we create this product right now called prod and the second one is as well bowl remove item from shopping cart simple as that and also all we're gonna pass is the integer which is gonna be our product id simple as that so now let's create a product let's do that before that and basically we're gonna do the same thing as we did before for a product which is basically gonna creating a record so public record product and we're gonna pass in which is gonna be an id string which is gonna be a name and lastly we're gonna pass the price any random information right now to be honest so that's what we're going to have we're going to have um didn't put the price so we're going to have a record which is going to be basically an id a name on a price we're going to utilize this inside our interface it's going to represent the database which has a couple of methods save item to shipping card and remove item to shop record and lastly we're gonna have the shopping cart functionality which is gonna be utilizing the idb service interface in order for it to inject this function inside the class so inside our shopping cart here let's do this what we're going to be doing is we're going to be initializing the idb service and we're going to just call it underscore db service and let's make it private i'll make it private just to be on the safe side and then once we do that we're gonna create a constructor and basically what we're gonna do is we're gonna pass this idb service to the constructor and then once we have done that sir press once we have done that we're just gonna initialize it so db service equal db service simple as that so now what we have here we have a class which has an interface inside of it and it utilizes constructor injection in order for us to initialize that interface perfect so once we have done that uh let us now try to create something energy for the shopping cart but before we do that i just want to mention something so if we let's say we are in a asp.net application and i have i have this for example this interface i want to execute please remember that this if you want to initialize it there it has to be for example services uh yes says for example inside the constructor could be services dot singleton for example and there inside that we put for example the idb service with for example db service and that's how we initialize it for example inside an asp.net application for example so we are trying to make that type of instruction this type of dependency injection what we're trying to make right now in order for us to do a unit test so i just wanted to clarify that out so once we have done that right now it's unfair for us to add some functionality and the functionality that we're going to be adding is as it says here simple shopping cart functionality so the first one that we're going to be adding is is basically adding stuff to the cart so public bowl the product and it's going to take a product and we need to make sure that the product is not not let's do it like that and first of all we're going to check if product equal equal null we're gonna return false return false then we're gonna check if the product dot id is equal equal to zero we're gonna also return false because basically these are invalid information so invalid parameters we don't wanna process them and lastly because it passed through our check sorry not false return no zero return false and lastly because it passed all of our check we need to actually pass it so it's going to be dbservice dot saved items to shopping cart and we're gonna basically pass the product and once we have done that we're gonna return through so that's gonna be our first implementation very simple straight to the point adding a product do some minimal checks and adding it to the database and memory database so now what we're going to do is we'll either delete a product it's going to be again public bool delete a product and it's going to take type id available end of type id why am i saying available and because as we said we want to create a way that we are actually consuming the application and when we think about it as a client and sometimes a client when they are trying to call an endpoint they might forget some certain parameter and that will be null so that's why we need to add this as a nullable end so again let's do the same checks f id equal equal null we're going to return false if id equal equals zero we're going to do the same thing return false and lastly right now because the it passed the first couple of sec we need to update it so we're going to say for example what was that dbservice dot remove from shopping cart and we're just going to pass the product id so because it's notable we need to convert it to n32 let's do it like this and once we have done that let's return true okay great so these basically are the two methods that we wanna currently test inside our functionalities for this show for the shopping cart so it's going to be ending a product and deleting a product and for this shopping cart what we did is we have injected the fake db service to our class through constructor injection so that's something that we really need to be careful about when we are trying to test it out so that's first things first so now that we have done that now we're gonna go into our testing up the test and then we're gonna basically add a new class which is gonna be solely responsible to testing the shopping cart so here let's see if this will work add a new class we're gonna put shopping cart test okay it added it here perfect so what we're going to be doing right now is we're going to be starting adding the unit test and we're going to do the same thing as we've done before but you might as soon as we start adding it you're going to see that we're going to be utilized we're going to be needing the db service in order for us to actually initialize it because as part of the three steps that we got there which is arrange act and assert we need to for in order for us to arrange we need to bust the db service and that's something that we're currently we're going to be doing manually but the goal of this is we're going to be actually utilizing mock as well admock is going to help us uh remove the need for us to add it manually and actually directly utilize and utilize the mock library in order for us to inject db service or fake and the an idb service to utilize it so let's start with first manually so first as we said if we're going to add a unit test we need to add a fact and basically let's remove this i don't know why it came like that and what are we gonna call this test and we're gonna just call it add product and successful that's gonna be the symbol of it and as we did before we need to initialize it so it's going to be for shopping cart equally new shopping cart but here shopping cart is basically not happy first because we need to add the the reference to it using the testing app.functionality the second here is if we hover over it it's expecting excuse me an idb service interface to be injected to it so it will be actually so it will actually work so that's what we're gonna be doing right now we're going to initialize an idb service manually and then we're going to pass it here so you might think to yourself okay how are we going to do this it's very simple so before this class here we're going to add another class and basically it's going to be public class let's call it db service mock because we are trying to mock an actual db service and this is going to inherit from idb service so basically what we did is we created a class and we have basically inherited from the interface that the shopping cart required which is idb service and for this to work we need to implement the two methods so implement interface we have these two methods perfect now we can we need to actually uh do some functionality inside the idb service so we can utilize it so because we don't really want to have that this is not nice okay so let's try to add the functionality first things first it's gonna be property of bool and we're gonna say process result why is that so basically what we want is what we want to do is we want to actually uh create our db service and basically because we are mocking it we want to for example tell the mock service what is the expected result that we want so let's say we are adding a product and the expected result is true we want to tell it that the expected result is true so the way we do that is we create here a variable called process result and based on that we can actually know the out potential outcome or the actual outcome of our operation so second thing is we need to property what are we going to be adding to the service it's going to require a product so in order for us to verify which product is being processed by this service we need to create a product and we're going to call it product being processed again this is all for demo purposes right now this is not how you write it the way we are doing it like this is for for us to understand what is required for us to have to be able to mock an interface or to mock a library and basically how actually how mocking will actually work and why do we need a library in order for us to make our life way more easier so that's the second thing the third thing is we need to have the id for this so public and i'm gonna say product id being processed all right we're gonna make it good and i said and that's nice okay once we have done that first thing first is here we can be to actually start implementing the remove from item shopping cart and save the item shopping cart so first things first so let's start with the remove and because we have said it here it's available we need to make it announable and did we make it here another but just me double check let's see no we didn't let's make it normal and let's make this nullable and let's remove these don't they need it because i forgot what did not make it nullable which is a big thing okay so let's go back here and we made this nullable perfect we made this notable because it was and now we need to implement the check so if id id this id is not equal to null we can actually process and basically it's going to be basic what we're going to be saying to remove is we're going to save the product being processed equal actually product id is just we're going to process the id product id being processed is equal to product id and okay this needs to be product id not id excuse me okay and let's convert this so convert excuse me it's a bit late convert to n32 let's do this right now let's pass this let's put this here and that should work and we need to add using system because we didn't add it using system okay great so first thing first we have done that once everything is processed we're basically gonna return through so we can put this like this so if product or we can do it like this if product equal equal null return false else it will return true it will be processed and it will return through okay nice so that's the first functionality that we want to have let's fix this make it look nicer okay so this is the first uh functionality the second one is going to be save so the same thing that we did before is we need to check if it's null or not so if we're gonna pass false return false perfect else if it's not null we're gonna add it so we're gonna put product being processed because we're just gonna make sure which is being processed we're gonna say equal prod and lastly we're gonna return through so again all of the smoking is we are just trying to uh mimic an action of a database trying to save something expected result what's going on how it's going to work it's just all trying to mimic a database and this is trying to do all of the mocking manually again when we introduce the library everything is going to be automated but for now it's going to be all manual okay once we have done that now because we have created this class dbmoc service if i copy this what i can do here is i can for example create now and initialize it we call db mock equally new db mock service and if i put here db dbmonk now shopping cart should be happy because it's actually implementing the idb service that we have and we can see that google has disappeared great so once we have done that the next step for us right now is to actually start implementing the functionality that we want to do so first thing first is because the expected result is true that i want to tell it what is the expected results so it will like so we can actually utilize it so for the dbmoc we can actually pass the process is hot we're going to say equal through because that's the expected result for us because if you see here we have introduced process result and the process result is a boolean and basically this is the outcome of the process that we want to pass so we're gonna we're telling it that for this db service for the next uh method that we currently have with the process result that we are expecting from you is true so you need to think about it that way so once we have done that and we have created the shopping cart now it's time for us to actually initialize the shopping cart so what we're going to be doing is let's create a new product so far product equal new product and we're going to just pass the end it's going to be an id the name is going to be shoes and the price is going to be 150 okay so that's gonna be the product now we need to add it so we're gonna call the shopping cart don't add product and it's gonna take what product correct okay once we have done that now we need to do the assertion and basically what we need to do is we want to assert the result so assert look through and basically in order for us to assert what do we want to assert as a true we wanna uh start the results so here we need to result equal so the result of adding a product we want to assert it's true and in order for the assert to work we need to add this x unit so let us explain what happened here first of all we have added the shopping cart and the shopping cart for it to work it needs to have an idb service available to it so it will mimic because the idp service make a database so that's the first thing that we want to do we initialize the shopping cart and we initialize the db service that the shopping cart utilize in order for it to excuse me to fake communication with the database but so how do we do that in order for us to do that and we have to mimic uh excuse me mock it manually we created a class which inherited from that interface and once we have created the class we want to actually mimic the functionality so we want to for example set the return type set the methods that the object that's kind of being processed and basically the idea as well so for these two methods we have set the result which is being the process result if it's true or false because he wanted it true so we set it to true excuse me here for example we're expecting false we should have this has been false and then basically what we're doing is once it has faked the process of that uh db service mock we're just asserting the results if you have any questions please feel free to put them in the comments down below and i will explain them as but i'll reply to you and explain it as much as best as i can if not in the comments in the next video so once we have done that the second step is we need to assert that the information is equal to what we have put it so we're going to put assert dot equal and we're going to be choose and we're going to assert the product uh excuse me the dbmoc dot the product being processed dot name so that's where one approach that that's why what we're trying to achieve so because dbmoc is actually representing a database in our case scenario uh where it's basically it means that it's to go to the database get the information of the product that we're trying to process and then based on that name that we're doing we want to match it to this and basically right now because we don't have an actual database we basically what we did is we just set it up to this product being processed here and we refer to it so that's the first one so let's save this and let us save okay saved and now let's run the test and now if everything goes to plan we should see that does succeed perfect so let's say we were expecting the result to be false and it's returning true so let's see what's going to happen so let's say i want to change the process result to false which is not the case because the expected result as we have set here in the shopping cart is true so let's see what's going to happen to that save this run this again should fail right now okay so this needs to be here excuse me so that's the expected or not excuse me for this so now let's try it again and now it should failed okay excuse me it's a bit late at night and i forgot to add the rest so that that needs to be assert dot equal we need to realize the result with the expected result from the database so it should be dbmock dot process result so right now this should fail because we have specified that the process is false and the application and the shopping cart's going to return through so let's save this let's try to run this and we should see here that this is going to fail we're going to give us a run that has failed because basically it gave us that one fade because this process result is giving us false although the results that the add product is what's expected is true so if we change this back to true and we save this and we run the uh that not test it should succeed right now because basically the expected result is true and we're getting back through perfect so now once we have done that the next step is we need to uh add more functionality and basically the current functionality that we're gonna be testing is the removable product so we're going to moving of the product and has to be successful as well so over before we do that let's add the ending a product but failed it's going to be similar to this uh let's try it out with a different reason for failure so let's put fact let's delete this let's delete this and let's start here we're going to be utilizing this symbol so we don't have to rewrite it again so let's copy paste this and let's so this is going to be db mock new db service that's correct the process result here is going to be false because it's going to fail and basically what we're going to be calling it here is going to be add product but it's going to be failed failure we're gonna put it you to invalid payload that's gonna be the case that we're gonna test so we have prepared it here we're gonna say that the process is gonna fail we have set it up and now we have to actually execute it so basically we're gonna put var result equal shopping cart dot add product and we're just gonna pass null and this should automatically give us a failure and if we just assert the result so this is going to be assert and we're expecting false so that's the expected value and the result needs to be false so that's the first test second test assert dot equal dot equal and this is going to be the result that we are expecting with the db mock dot process results so let's check this out let's run this perfect now we have four tests everything is passing as it should be so the next test that we're going to be adding is related to the product so let's add a fact and we're going to be posting is removing a product and we're gonna make it a success and basically we're gonna take the same thing copy this no need to rewrite and then we're gonna make this result as true and once we have done that is just take this as well uh where is it just take this create a new product edit no need to retype everything and basically once we have done that now we need to execute the functionality that it's actually removing because right now don't forget this is an in-memory database and every test run separately so right now even though we have added a product here by the time we're on the second desk is three setted so we need to add the product first and then we need to remove it so once we have added the product now it's time to remove it and basically what we're gonna be doing is we're gonna put var delete result equal shopping cart delete product and it's going to be product dot id and once we have done that now we need to assert the result so assert true because we're expecting a delete result through and then we're gonna assert that the equals of the delete results is equal to the dbmoc dot process result let's do this right now and let's run this perfect now we have five and all of them pass and basically here we can see how we have utilized basically mocking in order for us to execute multiple tasks on our functionality and basically how we have how we were able to fake an interface injection to our constructor for us to act to be able to utilize and as you can see here creating a creating a mock uh class and adding all of this condition and making sure we are passing the right variable and basically try to excuse me fake uh fake the entire journey and this is a simple uh class or simple functionality shopping cart right now it only had two methods so imagine if we had a class for example with 15 methods and everyone has a completely separate input and different configuration it's going to take a lot of time for us to try to mimic or basically mock the db service manually and once we have even mocked the db service manually we need to make sure that we have covered all of the different aspects and this and this is very time consuming and very much error prone because we're gonna of course we're gonna make errors right to creating a mock library for testing so for that reason there's a lot there's a lot of uh solutions out there and basically one of the main solutions is to utilize a nuget package called mock admob basically take care of all of this so basically mock the mock library is basically we pass to it what interface we wanna mock and it will be responsible to create the ins the fake instances create all for example the process result the the object that we're passing the if there's an id the id that we're utilizing and all of that and give it back to us so first of all it's going to remove the heavy load of creating a mock library from our side it's going to make it more easier to mock very complex structure with multiple inheritance or missouri multiple dependency injection as well on top of all of that it is much more stable than writing our own so what we're going to be doing right now is we're going to be installing this smok library to our testing project and then we're going to transform this code that we currently have to utilize that mock library so let's get started so first thing first inside our terminal terminal here we're going to add a package so it's going to be not add package and it's going to be more as simple as that few seconds and let's go here and we should see a mock perfect so once we have done that my advice as well is uh to always update the dotnet sdk here to 17 sometimes it face out of issues uh without not six so if you do this 17 unless to go back sorry not install it to run it so that not dust as you see everything is still but usually sometimes if you're having out of issues it says and uh it's not compatible something like that just make sure you update uh microsoft.net test sdk4.6 2017. just wanted to i just saw that and i thought i reminded you of this so once we have done that let us now implement mock so how are we going to be implementing mock let's go back to our shopping cart testing class so we have all of this here and this is all nice and hard work that we did but we don't really need it so what we can do is we can actually just do this i click the nice delete button and once we have deleted this we can see that all of this started to complain again oh i don't have my mocking library why are you doing this to me we're gonna fix it so let's see how are we gonna fix it so first thing first is inside here let's create a generic mock library how do we do that you might ask it's going to be public read only and we're going to basically do mock pass it's going to be a shopping cart we're going to pass the uh sorry in a shopping cart we're going to pass the interface that you want to mock which is idb service and basically we're going to give it a db service mock give it a name and it's going to be equal to new and let's fix those references so what happened here so first of all is what we did is we initialized the mock library and we told that that what you need to do let's go to terminal and what we need what you need to do is you need to create a full mock of the idb server similar to what we have done before and we have initialized it that's all we did we just specified the put the mock keyword we put the two brackets and we said you need to mock this idb service and mock will gonna take care of everything for us so once we have done that we don't really need this anymore because we have already defined the mock see the the number of lines that we're removing and now what we need to do is because it's requiring it so instead of having dbmo here we're just going to put db service mock dot object and that object mean that we are initializing an object or a fake object or a mocked object of the idb service everything is being done for us no need for us to do it manually all of this is being done by the mock library so as soon as we put the db service uh reference to the mocking library as soon as we put that object it's going to give a fake instance that we're actually going to be able to utilize in order for us to test so that's the first thing so once we have done that the next step here is instead of having this equal what we're going to be doing right now is we need to actually uh have some logic here not the object we're going to instead of having like a dbm db mock to process results we're going to add the right terminology or right keyword for the db server smart library in order for us to get there so let's do this right now so here for the result actually let's remove this because we're going to be doing it with the second one and actually just remove this right now and we're going to add a much more uh specific testing or assertion to do that so it's going to be assert or that's what the writers could do service mock dot verify so this is something that the mock rehability will provide us and basically we're going to be able to verify the results of our addition with the result that the shopping cart that ad has executed so we're going to create a lambda function and it's telling us what what method from the idb service you want to verify and we're telling it that we want to verify safe item to shopping cart and it's telling us okay what type of product will it take we can pass a product but we can tell it that you can expect any valuable because don't forget save item to shopping cart it expect a null or expect an object so we need to pay attention to that so how do we do that we put something called it and it basically hears uh if we go to it it says let me see if i hover it gives us an information so basically it allow us to have like a generic method of what do you want to have this parameter of this function is so we're going to put it that is any because any parameter will be accepted of type product so it could be a product or it could be not we don't really care as long as we are covered by this so once we have done that we need to actually tell it what is the outcome that we are expecting so on this outcome here it needs to be okay let's do this right now first so what what what happened here so first of all we have put a we have called reference the db mock service library we told that you need to verify something for us and we're telling it that you need to verify the safe item for the shopping cart telling it that your parameter that you are expecting could be anything of type products so it could be an instance of of a product or it could be null so that's why put it which refers to the uh collection of parameters that we can pass is any it could be like anything from poor product it is either a product or not and we're telling it that you have only executed once and that's why we did this right now right now if also we want to verify the outcome of it we can do this but first let's actually execute this and make sure that excuse me uh it's actually running as it should be so let's save this and let's run this okay as you can see shopping cart still not happy oh we need to update the rest uh let's update the rest and then we can execute so don't we don't need this anymore and instead of the even work here as we said before it's going to be db service object dot object and then here instead of mocking this we can take this take this and let's paste it here and let's do this with the same here let's delete these we don't need them and we'll put here the dbservice.object and let's do this right now like this and we need to update this because if this failed we're basically what what we are expecting here instead of okay so copy paste is always wrong but what can we do so right now here we just copy paste this and here this is not right because this needs to be uh never yeah why is this number because if this failed because here we are expecting a failure other product failure due to invalid payload correct and here we are passing a null which is expected here and we're expecting the results to be false so the result needs to be false it means that the it did not execute that it did not save anything to the database and here that should be as it is let's save this let's run this again does not test and we can see it everything has passed so let's do a recap here before we do a full summary so what we did is we have instead of mocking everything manually we have utilized this mocking nuget and basically what we did is we have initialized that nuget package on top this way we have initialized it mock and we specify which interface we want to initialize and once we have done that we refer to it here by once we do that object of that service it's basically creating an instance of that object and basically the in order for us to assert the result or making sure the result works we need to utilize the verify oh there's more than verify let's check this so we can put for example dbservers.mock and we can see that you have you can setup stuff verify so we have verify which is what we're doing verify dot add verify all verify guide verify remove verify sat all of these are built and right now we're just doing any generic verification uh for the sake of simplicity and because this is the first uh step of the uh seconds or the second step of the unit test when further modules are much more advanced unit tests we're gonna delve into more complicated items but for now we just understand this so we have verified it that this needs to be run and basically what we're verifying is how many times it should run because if it's run successfully it means that it has run one time and we basically were matching the execution time with how much time it has run we've had it's failed here it means that it have not run so basically the execution time is never which is zero and similarly to the success product here so let's run this again save and let's run the test.net test again we should see five out of five with everything green and flying color perfect so let's do now a quick summary okay so now that we have covered mocking and we have covered the basics of unit test our quick summary basically it's going to cover everything that we have learned today so basically the first thing that we have started is what is unit test which is basically testing specific pieces of code then we said why are we going to using it we specified all of the benefits that comes with it then we have one into the framework we as use as we said you can use any framework that you like but i highly recommend ax unit it's very fast it's very reliable and very modern and then on top of that we have specified the ingredients that we needed and then we have started building our application so basically what we did is we have created a console application we created some simple functionality inside our console application then once we have created this functionality we have created a new testing library utilizing the x unit once we have done that we started with creating our first unit test we decorated with the attribute fact and then we have went through the three steps range act and assert the three a's and basically the arrange mean that we are setting up our code in order for us to consume that part of code of functionality that we want uh the act is basically executing it and the arranged means that we are actually trying to uh sorry at the assert means that we are trying to compare the results and make sure that they are actually the outcome that we are expected so once we have done all of that uh from the simple functionality that we have added the next step for us was actually to add a bit of a much more complicated functionality which is going to be the interface injection to our application so once we have actually injected the interface to our apps application so for example you have added the new functionality and that functionality was called shopping cart inside the shopping cart functionality that the thing that we did is basically we have uh have a fake idb service and that idb service has been injected to our shopping cart through constructor injection once we have done that we added some functionality here and there to our shopping cart once we have added that to our shopping cart we created a new class inside our testing class library once we have added this inside our testing class library we needed to actually write some unit tests so again we put the fact we put the uh excuse me we have put the uh arrange act and assert once we have put the arrange act and assert there whether we needed to in order for us to arrange we needed to actually initialize our shopping cart but because the shopping cart has already been utilizing the idb service as an injection for it in order for us to avoid that work uh actually not to avoid that in order for us to accomplish that work what we needed to do is actually first to uh create a fake dbmock of our application of our idb service so we created a class the other class inherited from the idb service that we have created we created all of the mocking that we needed manually there and then we have instructed it to our unit test it's not the best way but we did in order for us to understand how mocking work once we have done that we have added all of the rest of the unit test and it worked as it should be but then we saw the level of complexity that it has introduced so after that what we did is we have created the uh we have created we have added the nuget packages which is called mock once we have added that new that new get packages which is called mock to our library we have deleted all of the manual mocking that we have done and basically we have utilized that mocked library inside our unit in order for us to actually execute this unit test utilizing the mocking library and basically we have we have seen that the amount of code that we have removed and make it was very it was a large amount of code which made our uh unit test way smaller and much more impact and direct to the point and we have so there how we are how we have actually utilized mock inside our units in order for us to execute those tests so that was a quick summary of everything we have accomplished today i hope this was a very helpful introduction to unit testing there's going to be a couple of video after this going in more in depth of how we can actually do more you do more unit testing covering different aspects of unit testing calling a http request inside our asp.net application so on so forth any questions please write them down in the comment down below as well if you have any ideas or anything you would like to me to cover for unit testing also please mention it in the comment down below and i think if you made it this far inside this video it means that you actually like this video so please like share and subscribe if you like it it will really help the channel as well type your favorite type of fruit inside the comments that way i know that you have made it this far and you have watched the entire video thank you very much for watching watching and have a good day
Info
Channel: Mohamad Lawand
Views: 28,333
Rating: undefined out of 5
Keywords: dotnet, csharp, aspnetcore, api, unit test, unittest, moq, xunit, testing, automation, dependency injection, interfaces
Id: AW7ZcMOtwC8
Channel Id: undefined
Length: 89min 24sec (5364 seconds)
Published: Fri Jan 21 2022
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.