Software Testing with Spring boot and Mockito Framework

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
today we're diving into a topic that's not just crucial but can make or break your software unit testing in Spring boot with a powerful mokito framework I know some of you might be thinking why bother with unit tests my code works fine well back a up because we're about to embark on a journey that will not only answer this question but will revolutionize the way you approach building robust and Reliable Software but before we jump into the nitty-gritty of unit testing let me paint a scenario you've built this incredible spring boot application right it's got all the bells and whistles interacting with various Services databases and whatnot now imagine you make a small change a tiny tweak in one part of code everything seems fine on the surface until suddenly your application decides to throw a tantrum in production chaos panic and a barrage of angry users not the scenarios you want right so this is where our superhero comes into play unit testing and our Sidekick mokito is here to save the day by helping us create a controlled environment for our tests ever wondered why we need to mock Services stick around you'll discover the pivotal role it plays in ensuring your tests are reliable isolated and effective we're not just writing tests for the sake of it we're building a safety net around our code with each test we gain confidence that our application behaves as expected even when we make changes and trust me in the fastpaced of word software development that confidence is really good now join me on this journey to domestify unit testing explore the wonders of spring boots and unravel the secrets of mokito together we'll Empower you to write code that not only works but stands resilient Against the Wind of changes back it up hit the Subscribe button smash the like button and help me grow this Channel and spread the knowledge everywhere and let's dive into the fascinating word of unit testing in Spring boot with mokito ready let's roll implementing tests for a spring boot application is important for several reasons first we talk about quality assurance so tests help ensure that your application functions as expected they identify bugs error and expected Behavior early in the development process allowing you to fix issues before they reach production and then regression testing as you make changes or add new features to your application tests act as a safety net to the catch regressions they ensure that existing functionality continues to work as intended even after code changes also test serves as documentation for your code base they provide examples of how your code should be used and demonstrate its expected Behavior this is especially helpful for other developers who may join the project later on also a well written tests encourage good coding practices and modular design they often lead to the more modular Loosely coupled code that is easier to maintain and refactor when you want to refactor or optimize your code tests provide a safety net they allow you to make changes with the confidence that you'll immediately know if something breaks also the test facilitate collaboration among developers when multiple team members are working on the same codebase tests ensure that changes made by one developer don't negatively impact the work of others also in a cicd pipeline or like continuous integration continuous deployment pipeline tests are run automatically whenever new code is pushed this helps catch issues early in the development process and prevents faulty code from reaching production also wrting tests can take more time up front but it can significantly reduce the time spent on debugging later in the development process it's much easier to identify the root cause of a failure when you have a well- defined tests as your application grows the complexity also increases tests provide a safety net that allows you to confidently make changes and add features without introducing unexpected issues and finally of course tests certain types of tests like security and vulnerability tests help identify potential security weaknesses in your application this is crucial for protecting sensitive data and ensuring the overall security of your application so generally speaking in a spring wot application you can Implement various types of tests including unit tests integration tests and even endtoend tests so each type of test focuses on a specific aspect of your application functionality and provides a comprehensive safety net to ensure its reliability and correctness now let's see how spring can help us in implementing the test and what spring provides exactly so first spring provides utilities and annotations for testing applications so the test support is provided by two modules the spring boot test contains core items and the spring boot test autoc configure supports Auto configuration for testing and then we have also the spr spring boot starter test which Imports the following modules first of all we have the spring boot test module we have also junit assertj hum Crest and number of other useful libraries so a springbot application is a spring application context and this I will explain it more in details when we go to the practice part so the spring boot provides a spring boot test annotation when you need spring boot features during test so for example if you want to load the application context in your tests all you need to do is to annotate your class with the springbot test annotation and then in case you are using junit 4 you need to add The annotation run with spring runner. class to your test otherwise The annotation will be ignored other than that if you are using junit 5 there is no need to add the equivalent extent with spring extension as the spring boot test annotation and the other annotations will be already annotated within the at Spring boot test so now we mentioned that spring comes with a spring uh spring test Auto configuration module so the spring boots Auto configuration system works well for applications but can sometime be a little too much for tests so it often helps to load only the parts of the configuration that are required to test a slice of your application so the spring boot test autoconfigure module includes a number of annotations that can be used to automatically configure such slices and finally each slice restricts component scan to appropriate component and loads a very restricted set of autoconfiguration classes now we are done with the theoretic part this might be a little bit too much or like too much talking now we will move to the practice part and you will be able to understand and start implementing tests your own so let's move on and let's go ahead and do it all right now let's dive into the implementation of tests for our different classes so here this is the diagram or the composition or the the class diagram of our small application and I'm focusing only on the student domain so here we see from the bottom to the top we have the student composed of the student service this means that the student controller uses the student service and the student service use both uh of student repository and student mapper and the student mapper will use both object student and Student Response dto so now I want to tell you and explain to you you what you need to implement test for so what do you need to test which classes and which objects you need to implement tests for so here we see that the Student Response dto and the student object they are just classes so there is no logic inside it so it's just a class holding some information about the student and this class or this record is only holding some information about the Student Response dto now if we go a level down we see that we have the student mapper and and then we have the student repository so the student repository we can also Implement test for that but it doesn't make sense or it's not really required to implement tests for repository so we will skip this one now let's start with a student mapper so the student mapper right here so if we go to the navigation or if we navigate to the student mapper right here to this class we see that we have two methods all right so now I want you to change a little bit your mindset and suppose that you don't know the code before so you just have a mission or you're asked just to implement tests for this classes so here we have two methods to student and to Student Response dto so the first one will return student object and the second one will return a student response dto so normally from the name of the method we can understand what is its functionality otherwise we can go ahead and read the code so we don't need that because we already implemented this our own and now what we need to do is to create a test class for this student mapper so to create a student mapper test class let's start with the recommendation so here we see that we have the Java and this is the base package that we have which is com. alibu example and then we have school and student and student profile and so and so forth here if we check the test we have also Java and then com. alibu do example and here we have also example application test which is the same or like the same loader class or the class that will load the application context for our test so for now we will just ignore this one and I will explain it in the coming sections all right now the first recommendation is when you create a test class for one of the for one of the services or the classes that you want to test be sure and make sure that you keep the same package naming so you you need to keep keep the same hierarchy of of packages and folders just to make it easy to find so you can just create it anywhere or like even without creating packages but the recommendation to make your test classes clean and clear and easy to understand and easy to point you just need to keep the same hierarchy or like the same package hierarchy and we are lucky because our IDE whether you are using anj Eclipse net beans and so on so forth you always have some shortcuts and you have the instruction and menu to generate test classes for the class that you want to test so here if I open back my test student or like my student mapper class and I want to generate a test class for it so if I do like um right click and then let's click on generate right here so here we see that we have many options and among these options we have test so if I click on test you will see that it will be it will be generating a student mapper and then it will have or it will give it a suffix called test all right and here you see the destination package it will be com. al. example. student you can select a different one or you can change the name and so on so forth but as I mentioned before I recommend you keep the same the same hierarchy and then you also can generate methods for setup tear down or also showing the inherited methods and even you can generate two methods or like two test methods for the two student and two Student Response dto but for now we won't do that we will do it one by one and step by step so I will cancel then we have a different option so here just um focus on this area you will have this green popup to show you which um command or which shortcut or keyboard shortcut that I will be using in order to navigate to the test so here if you do uh command shift t or Control Plus shift plus T if you are using Windows or Mac until J will try automatically to navigate you to the test class of this student mapper all right but if it can't find any test class it will suggest you to create a new one so it will also open and display the same window that we used before or that we saw together before and here for the testing Library since we are using Java like recent version of java and also like a recent version of spring boot so we we can keep or we can use the junit 5 also if you have another project uh using junit 4 for example I already explained that before that you need to add few annotations or like one annotation in order to make it work so now all we need to do is to click on okay button and here you see that automatically a new package was created and it contains a new student mapper class test all right so now we have everything ready let's go ahead and start implementing or let's start writing the first test method that we have for our student mapper class all right so first of all let's generate a first test method to create a test method all you need to do is to create a public void so this is the signature and this it should be always public void and then the method name so let's call it test method one so this this will be the first test method and the test method is a method without any parameters so here to make this test method as a test method so all we need to do is to add The annotation test so the test it comes from org. gun. jupiter. API so here once we add this test you see automatically that now we have this button to run this single method or you have this button button right here to to run all the test methods inside this class so let's first of all just add a system.out.println and here my first test method and now let's run this test class using this play button to run only this method since we have only one or if we want we can run the whole test so let's run student mapper test class and then you will see that it will open the test View and here we have the system.out.println the message that we printed my first test method and the test was green since we have nothing to assert yet we will come to this in few moments but before that we need to understand what are the properties and what are the things that we can do within a test class so the first thing that we need to know is that we have a setup method or we can create a setup method so if if you click on generate here you will see that you have a setup method you can generate it automatically or you can even write it your own so let's generate it and see what it what is this method so it's just a void called setup and it contains an annotation called before each so this means that this before each method or this setup method will be executed before each test that we have and we mainly use this setup in order to initialize few things or few parameters or anything that we want to initialize before running any test method that we have so I will just copy this message right here and here I will just write inside before each method and now if I run again my class let's see what will be the output so here we have if I click in here we have inside the before each method and then my first test class so now I will just duplicate cre this method right here and I will call it my test method two and here I will say my second test Method All right so I will rerun again the class and here we see that this one we have inside the before each method my first test and here we have also inside the before each method and then my second test so as I mentioned this before each will be executed before each test class so in case as I mentioned before in case we want to initialize anything before running the test Method All right so also as before each we have other methods and let's go ahead and explore them one by one in order to understand the structure of a test class and what are the usages and the benefits of using these methods all right also if we want to execute any script for example to reset the values of variables or classes or services or whatever we also have a method we call it tear down so the tear down is after each execution of test method so here let's use the generate again and here we see that we have the tear down method so let's generate it and here you see after each so let's copy the same message and here inside the after each method when we run the test class we will see inside before each method and then my first test method and finally inside the after each method so let's go ahead and execute it and see the output of this execution so now I'm going to select the first method and as I mentioned we see inside before each my first test and then inside after each so as I mentioned before in case you want to reinitialize or for example to change the value of a specific attribute or for example if you are running your tests against database so you can just initialize and insert some data in the before each and after each you can delete them or re-update the data in order to be able to use them in in the next Method All right so now let's move on and let's see what are the other methods other than the before each and after each all right now the question is what if I want to execute a setup or to initialize few attributes and variables only before the execution of the the whole class so I don't want to run this method before each method but I just want want it to be executed only once so in this case we have also another method so let's click on generate and here we see we have a before class so when I use a before class so it's called before all again I will copy this message and here I will say inside the before for all method so now when I run my test so you can whether run it from here or again click on this play button or just run one of the tests so let's go ahead and run and rerun the whole class and see what we have so for example let's select this one so here we have first when we select the method we see only these three output messages which is the before each the method and then the after all but when I select the class we see that we we are inside the before all methods and then inside the before each method and the after each method and we have it again for the second method so now just I want to make this output clear so I will be running only one method so like that you will see it in a better way so now we see that we are inside the before all method and then inside the before each my first method and then inside the after all method so this is the case if I they want to initialize something a service for example or to create a new instance of an instance or an array list uh or something like that but I just want it to I want to do it only one time I don't want to do it each time so in this case we need or we use the before all method so now in the same way we have another method called after all so let's go ahead and try this one and then let's move to the real implementation of the real test case of our student mapper class all right in the same way let's generate an after class or an after all method and again I will just copy paste and here inside the after all method so if I run one of the test classes or the test methods that we have and here let's go ahead and check the output so here we have inside the before all and then inside the after all and in between we have the before each the the test method and the after each so the use case of the after all and the before all is for example I want to initialize or insert some data into my database in case we are using for example an inmemory database so I want to insert some data and then once I'm done I want to remove them for example or even if I'm working against my Dev environment uh database or something like that so in this in this way we can initialize data work with them and once once we are done we can remove all the data that we already inserted so in this in this way we are safe from polluting and inserting wrong data into our database all right so now you know the structure of a test class what are the methods that we can use within a test class so now let's go ahead and start implementing few test cases for our student mapper class all right now let's start implementing our tests first of all let's start by cleaning up all this code so let's remove it and also let's reoptimize the Imports and now let's implement the first method so here just to remind you we have our student mapper class that performs a mapping so it transforms a student dto to a student object and then we have to Student Response and it transforms a student to a student response dto so now coming back to our student mapper test so here the first thing that you need to do is to declare the service that you want to test so here we want to test our student mapper so let's create an object of type student mapper and then let's call it mapper for example and then the first method or like the first use case or the test case that we want to implement is that we want to make sure that these two student mapper performs a correct mapping from student dto to the student object so here let's create our first method public void and let's call it should map student dto to student class all right so this is our first method and to make it a test method we need to add always the test annotation so then you see that this student mapper right here is not yet instantiated so we don't have an instance or an object of types student mapper so it's just the variable or the field so now we have two options whether to initialize it in here so we can do new student mapper or we can use one of the test of of the setup methods so here we can add a before each and then we can move this part right here to this setup method so we can make it this way or the other way round so let's go ahead with the before each so now we have our mapper object initialized and now let's start creating and implementing our first test method so here the first thing that we need to do we need to create an object of type student dto since this is the input of our two student method so now let's go ahead and do it so here we have an object of type student dto let's call it dto equals new student dto and for this let's call it John and then for the last name name let's call it do and we have an email so John mail.com for example and then we have an INT the school ID so in this way so I'm going to just inline this one so in this way we have our student object so after that all we need to do is to call this to student method so here let's create an object of type student and let's call it student equals our mapper DOT to student and then we pass the student dto and then we will start asserting that the output of this mapping method is what we expect so here let's go back to this two student method and we know that we when we call this student method we just set these fields and then we have an object of type school so again we can test so what we want to focus on is that we have also a mapping for this school object and that we have all the fields not changed so now let's first start by asserting and in order to assert so here we have assert equals and this assert equals so it comes from assertions so the assertions is from the package org. gun. jupiter. API do assert equals and here for the assert equals we have multiple implementations so we can assert equals shorts bytes uh strings integers and so and so forth so here let's do assert equals and then what we want to test we want to make sure that our dto doget first name to be equals our student object. getet first name so here we want to make sure that this first name is the same for the class student all right so now also we can import statically this assert equals and we can do that by add static import for the unit uh Jupiter API assertions do assert equals so when we do that and when we go up so you will see right here that we have a static import for that method so the next time you see assert equals or any static usage of a method so you know that it's statically imported in here all right so now let's continue the assertion and here we have the first name let's also test the last name and here get last name and after that we have the email and also here get email and finally we want to make sure that this the school is not null so here for example we have the assert not null so as you can see here so I want to assert not null that my student. getet school is not null all right so then we can also make sure that the school ID was correctly set so what I can do we can assert equals so our dto do school ID is the same as student. getet school.get ID so at this level we are safe because we have an assertion that the school is not null but if we change the order we might encounter a null pointer exception in case the school is not correctly mapped so now let's just just go ahead and run this test method and let me show you what is the impact and the execution of this method so here we see that the method was green but now you might ask the question I'm just making sure that this object that I created manually is the same as I called this method so now let's go to our student and for example let's say that I forgot to set the school to the student object and now if I go back and rerun again the test let's see what will happen so here we have a test failed so here we see that expected not null but the object was null at this point so here you see that assert not null of the school so this means that the school was null and I'm expecting the school to be not null so now step by step you see the importance of having unit test within our application so let's go back to the mapper and let's bring this back and then for example let's say when I transform the first name or the last name I just I just do to uppercase all right so I transform the first name to an uppercase if I rerun the test again you will see that the test will fail and here we see this message so here we have assertion failed error and the expected was John which is the object right here that we initialized with with our dto and the output was drawn with an uppercase so this is also another or a different assertion level or an assertion test that we make sure that the input should be exactly the same as the expected output all right so now let's go back to our mapper and let's just remove this one and in case for example you have changed the implementation of these two student method you need also to update the test okay so in this case you make sure that everything works fine so let's run the test one more time and make sure that everything works fine so our test is green now we can move on and Implement other tests all right so now since you know and you understood how to implement tests so I want to give you a small exercise I want you to implement the test method for testing these two Student Response dto and it should take a student object and then return a student response dto so you can also Inspire and follow the same example we did right here I want you to create another method and you call it should map student to Student Response dto so I will let you do it and I will provide you the correction in the next lecture that's good I was sure that you will implement it correctly so let's do it together all right so first of all we need to create a public void method and then let's call it should map [Music] a student or student to Student Response dto all right and then parentheses and then the brackets and don't forget the test annotation all right so the first thing as we did before we need to create an object of type student all right so here go student student equals new student and then let's initialize our student object so here let's say Jane as a first name and then Smith as a last name and then let's provide an email so Jan mail.com and then we need an age let's say for example it's 20 and let me inline this all right so now we have our student then all we need to do is to create an object of Student Response dto and let's call it response equals our mapper and then to Student Response D and we need to pass our student all right now comes the assertion part so the first thing we need to do is to assert first name last name and email and make sure that the result is the same since within our Student Response dto we only have three attributes all right so now let's say assert equals and then I want my response. first name to be the same as my student. getet first name the same for last name so here last name and then get last name the same for the age I want the age to be the same as the student. getet AG uh sorry we don't have an age for the response dto but it's email and here it should be the same as get email all right so now let me add a few comments so here how how we can read the test so here we have given a student object and then when we map the student to a Student Response dto then I want or I expect this result so now let's go ahead and run the test and make sure that everything works fine and we did not forget anything so the test is green Also let's go ahead and run the whole class and here we have all the tests are green and passing okay so that's it let's move on and let me talk to you about something really really important when you implement an application and mainly you can detect that with the tests all right now let me talk to you about something else so here I will just start by creating a new test method and after this method I will just create a method called public void and then this is also a different way of writing the the method name so we can write it in this way should map student dto to student object all right but this new method I want to add if or let's make it when student dto is null so this means I want the mapping to be or to perform correctly or in an expected way even if the student dto that I'm passing right here is null so what I will be doing I will just copy this part right here and then paste it in this method and instead of passing the dto I will pass a null object so here what I will be doing let's say for example so we will change this later on but let's start expecting this so here let's say an empty string and here empty string all right now if I run this test method let's make it a test and if I run this test method let's see what will happen so here we have a NP pointer exception cannot invoke the student dto do first name because dto is null all right and the exception happened inside the mapper itself so if I click here we see that the the problem is exactly in here because we are trying to get the first name from a null object and here we mainly talk about code coverage so we need to cover all the use cases that our method and our service class and our class generally speaking should handle so here you see and you noticed that we did not handle the case when we pass a null dto object so in this case what we need to do we need to go back to our student mapper and then we need to add a test or a check or do whatever just to make sure that when we receive a null object we want to do something whether raise an exception or just printing a message or even for example initializing an empty student object with for example let's say empty values so the implementation always depends on the requirement of of your story or of the application that you are implementing so now let's go ahead and start doing this so in this case or in this use case we will see many things so the first thing let's go back to two student and here I want to do if my dto is null for example I want to throw a null pointer exception all right so here we need the new keyword so a new n pointer exception and here the student for example as a message the student dto is null all right so now we add we added a coverage to our method so now let's go back to the test and make sure to readjust the test right here in order to make sure that this student method should throw a null pointer exception when we get get n dto student so we don't need this one since we don't have any assertions and now let's just rename this method to make it more relevant and here instead of should map so let's say should throw and then a n pointer exception when student dto is null so now we have this mapper do to student and then we are assigning it to a student so we can also remove this assignment since we know that it will throw an exception and it will return nothing so now how can how can I expect or make sure that these two student is going to throw a null pointer exception so in order to do that all I need to do I need to assert that this method is going to throw a null pointer exception so I'm just going to remove it and now I'm going to use assert throws so here this throws method first of all it gets the expected type so in our case it's a null pointer exception do class and then it's a Lambda expression so here when we call the mapper do2 student I'm expecting to have a null pointer exception. class thrown so let's run this method and make sure that it passes green right now so now this method is throwing this exception so now what if I want to check the message that the message should be the student dto is null or should not be null so here let's just rename it should not be null and I'm going to copy this message and now I will go back here so in order to do that all I need to do let's create a VAR message equals this so as you can see this a assert throws it will return the exception itself all right so now if I do MSG Dot and here I have access to the method get message from the null pointer exception or from the exception generally speaking so now I I want to do assert equals I want this error message to be equal to my message or exception. getet message so let's just rename this one to exp to say it's an exception so exp for exception and now if I run again let we need to be sure that the the method through this exactly the correct error message so here for example if I add a DOT and run again the method should fail and as you can see now the method failed and the assertion failure is we are expecting this but we got this one so in this case we gained two things the first one is that we add a coverage to our two student method and then we also covered this with within the test so for example in case I want to change from null pointer exception to a different exception it will be automatically detected by this test method again if I change for example the exception message it will be also automatically detected so now let me run it again and make it green and now we added a new coverage to our method so this is how you can test exceptions and this is how you can catch exceptions and make sure or you can do whatever you want even if you work with custom exceptions that you create your own you can also capture that and do whatever you need to assert everything as expected all right so now let's move on to the next part all right so we finished the implementation of the student mapper and we saw how we can create a test class how we can create test methods also we saw how we can or how how much we need to cover our code like we need to cover all the use cases now let's move and start testing or writing tests for our student service so we know that this student service is a spring component and it has a strong dependency with student mapper and the student repository and especially when we talk about student repository we talk about communicating with database so when it comes to testing how can we test and how can we tell spring or this student service that we have a student repository and this one needs to communicate with the database and what happens in case we don't have a real database for testing because testing it does not necessar necessarily need to have a database for testing so that's why we will talk about test isolation so test isolation means that we want to run and to write tests for this student service in isolation of its dependencies in a different way I want to execute and write test for this student service but I don't necessarily need to have the the real instance and the real object of my student repository the same for my student mapper so what do I need to do I need to mock these two objects so to do that we have there is a framework called mokito so mokito is a popular Java testing framework that helps you create mock objects and stab behaviors when writing unit tests so it's especially useful when you want to isolate a specific component of your code and test it in isolation from its dependencies so now we know what we need to do we need to isolate and we need to mock so you need to remember this term we need to mock our objects we need to Mark the student repository and the student mapper to be able to run the student service test in an isolated way so let's go ahead and let me show you how we can isolate and how we can Mark the objects and the methods for each service that we have right here so now as always the next step is we need to go and create a test class for our student service so all I need to do navigate here and then command shift T and create a new test so here we don't need any of these we just maybe need or use the setup method so I will just check it out and then click on okay so here we have hour before each and we have our student service test class so as we did for the student mapper what we need to do here first of all which service that we we want to test so in this case we want to test our student service so I will create an object of student service and I will call it student service and then when it comes to objects that have dependencies let's check in here so we see that our student service has two dependencies that we need to inject all right so our Constructor is a Constructor with parameter and it requires an object of type repository and an object of type student mapper so let's just go ahead and do that I'm just going to copy this one and in here declare the dependencies all right I'm going to paste this and then I will just fix the codes all right so now I have my service and I have the dependencies so what I need to do so we said that in order to run the student service in an isolated way what we need to do we need to Mark the student repository and the student mapper so what we need to do there is an annotation called mock so this mock annotation comes from or. mokito it's not the one coming from the or. spring framework we won use the the mock from or. mokito so let's select it one and the same we need to add it to our student mapper so in this in this way we are telling our test class and the moito framework that we want to create mock for this repository and a mock for this student mapper all right now how can we tell this mocking framework that we want to inject these two properties and these two dependencies into this service right here so the answer is kind of straightforward because I just mentioned injecting so we have an annotation called inject MOX so inject MOX always is coming from the or. mok2 package and like this our mocking framework will try to find any dependencies annotated with the mock annotation that is compatible with the dependencies that are required from our student service so this means when we try to create an instance or to initialize this student service the mocking framework will look for two object annotated with the mock annotation and that are of type one of them is of type repository and the second one is of type student mapper all right so now we prepared everything we still need to do one more step so then what we need to do we need to tell the moito framework that we want to open the mock or like we want to start the mock for this current class so this means that in the before each here what we need to do we need to use the moito annotations class doop Mox and this open MOX takes an object which is the test class as you can see right here so let's give it this because we want to open the mock for the current class all right so may you you might see this warning right here this is because the open mock methods return an autoc closable so and this the anj or your IDE will recommend to you that you might need to you might want to use a try with resource but we can ignore that for the moment it's not something really important or really uh going to break our test all right so now we set up our test class now let's move on and implement the first test method that will allow us to save a student so the first one it will be this save student that's good now let's analyze our save student so we have here first of all we are doing a mapping and then saving the repository and then again we are doing a second mapping so this is what we need to test in our test method so let's go back to our student service test and here I will create a public void and then should successfully save a student all right so this is our test method let's not forget the test annotation and now here let's remember the given when and then so here given what so here in our save method we have a student DTU so let's first of all create a student DTU object so let's go back here and here I have first of all my student dto object also this class it is going to need an object of type student which is this one so let's also go ahead and prepare our student so it will be almost the same so just copy the signature right here and here I will create an object of type student let's call it student equals and then new student all right here let's remove this one all right here we have also our student object and our student dto so what we want to do or like how this is going to work this means is when we call our student service. saave student we are expecting an object of type Student Response dto all right so here I will create an object of type Student Response dto I will call it response dto equals our student service do save student and then we have a dto so this is the dto that we will pass as a parameter and then what we need to do is to start asserting so let's say assert equals and then we have our dto object. getet first name should be equal our response dto doget first name all right let's do the same also for the last name and also the email so we can stick just to these few fields we don't need to test everything so this is what we want to test so now if if I run the test what should happen so let's go ahead and check together so I will run this test method and let's see what will be the output here we see that we have a null pointer exception saying that we cannot invoke Student Response T do get first name because the response o is null and this is happening in here so this means what I'm going to just add a breakpoint right here and I will run again this test in debug mode so here let's see our student service so we have an object since it's already mocked the same for our repository so we as you can see we have a moito Interceptor and so and so forth so now if I evaluate this expression and then evaluate expression and then evaluate we see that the result is null okay so let me explain to you why we have this null result so this null result is because the student service is is trying to call the student mapper and then we have the student repository is also going to call the save method but remember here we have a mock so we don't have the real instance or the real service running for our test because we decided to run our student service in isolation mode so to do that what we need to do here we need to mock the calls so which calls that we need to mock we need to Mark every call that uses another service or another dependency in our student service and in this case we have the student mapper and we have the repository. saave so let me show you now how we can mock these calls so the first thing that we need to mock is the as you can see here the first thing that we that we do is the mapping so let's mock the mapping all right so now in order to mock the calls so the first thing that we need to mock is our to student so student mapper do to student method so this comes from mokito we have a static method called when so this means when we call a method so we have as a parameter the method to call so here we have student mapper dot to student so when we call these two student with our dto object so make sure that the mock will work only if we pass this object right here so then what we want to do then we have so many options so we can return we can return whether a student we can also a student and a list of other students we can return an answer or we can even throw an exception so in our case we want to return an object which is our student right here so let's return the student and now we are done with the first mock of our student mapper do to student student method so here when we say when we are mocking a method all right so this when we call the student mapper2 student dto then we need to return this student object so this means that our student service will run in isolation mode and it does not 100% depend on the real implementation or the uh not the real implementation but the real instance of the student mapper so also let's import this in statically so when student mapper then return all right so let's do the same for our repository so when our repository dot save and then student then return our student itself all right because we know that when we save a student we return another student or if you want to be more consistent or if you want to have like more uh details you can even create another student object you can call it like saved student student and set the ID and set everything and also you can return that one so let's just do it it's it's totally fine so I will call it saved student and then I will just do saved student. set ID and let's give it the ID number one and in here I will return our saved student all right so now we have three objects so first we have the dto and then the student that will come from the mapping and now this is the student that should be saved in the database so now again we mocked the second call which is our repository so if we go back in here we still need to return another call so here we need to mock also the student mapper dot to Student Response dto so in order to do that just in the same way so here we have when we call our student mapper do to response dto of our student object which one which is the saved student all right so here we have then return let's now just return a new student response dto and all we need to do is to pass the first name last name and email so this is the first name last name and email so let's just copy them from here so we have our John do I'm also going to inline this so you can see the full code and the email is just John at email.com all right so now we have our test set and ready so let's go ahead and run the test right now and see the output so I'm just going to click and run this one and let's see what will happen so now our test is green so we have all the expectations and everything was running in a successful way because we have here we mocked everything and in case for example I I just change anything or you forget to uh to mock a step your test will fail that's good now we created our first test method and we saw how we can mock objects and also do some assertions so this is the classic assertions but now what if we ask the question how can I check that my application is performing well so here for example in this save student I want to make sure that I only save one time the student into the database this means for example I don't want to have some error or like someone typing two or three times this repository. save because this will save the student many times and in case for example you have a unique constraint it might throw an exception and this will break the application so let me show you how we can prevent this from happening so if if I go back to my student service right here we can do this in the same place since we have our code already set up all right so here we are mocking and now what I want to do I want to make sure that this student mapper2 student was called only one time same for the repository and the same for this one all right so to do that mokito also provides us with a method called verify as you can see here so we want to verify and then we need to to type the mock object so our mock object is the class or the instance itself and then we can pass a parameter so it's a verification mode so here we have okito do times also we have timeout we have so many other options I can for example check that a method called should take only just just as an example should take only two seconds maximum to be executed if it goes beyond 2 seconds the test will fail and like that I can also make sure that I have performance issues with my application all right so now let's continue with these times so I want to be sure that this student mapper dot to student and then the object student dto or the dto object that we created it has been called only one time all right so let's do the same for repository and then times one and then the save method when we pass the student object again I will do I will duplicate this one and here's student mapper and then to response dto or to Student Response dto and here just to make sure that we passed the saved student as an object all right so here we need to say saved student all right I'm just going to align these methods right here just so you can see everything so here verify that this method or these three methods of the different Services were called only one time so let's go ahead and run the method again so run this and then the test passed so now let's suppose for example that one of the developers or me for example as also as a developer of this application I accidentally forgot to remove this extra line all right so now if I rerun the test again let's see what will happen so the test will fail and we will see here that wanted one time so this means that we wanted to have our call only one time but it was called two times and here so as you can see here you have student service do save student that was called two times all right and it was pointing to here and then to here so here we see that even the test will point us directly where the issue has happened all right so that's good now let's move on and let me give you a small exercise and I'm pretty sure that you will be implementing it really easy without any issues now let me give you an exercise I want you to implement the test for this find all students so it needs to cover and to make sure that when you make a call to this repository find all it should return the exact same list that you already expect and in the next lecture I will show you how to fix this one all right that's good I'm sure that you correctly implemented the test for this find all student but also let's go ahead and do it together so I will create as you usual a public void and then I will call it should return all students and then we have the given so for the given the first thing that we need to do is to create a list so let's create a list of students so this is the object that will be returned so let's call it students equals new array list and then let's add one student so student. add and and we can even copy the student from the previous method right here so I'm just going to copy this one and I will insert this student here all right so now we have one element in in our student list and then we need to Mark the calls so the first call that we need to Mark is when we call our student repository or the the repository object do find all then I need to return the students list that we created all right and then what we need to do we need to Mark the call for the mapping all right so here we have when mapper or student mapper dot to Student Response dto and here since we might add or pass any student so we can use the power of moku and here we have argument matchers do any and here when we say any we can also spfy the class so when we receive any class of type student do class then I want to return for example a new like a new object of type response Student Response dto something like that so I'm just going to in line this so when we call the student mapper do to Student Response dto passing any object of type student we want to return this object we can also make it more Dynamic but for the sake of a simple um test case it's also easy and it's also okay to make it like this and here we just forgot the test annotation so we need to add it and now all we need to do is to have a list of type Student Response dto and then let's call it response dto equals our student service do find all all right and here so this is given and now it's when when we call this one so then so here for here we do assert equals that our students list do size to be equal to our students dto do size or response d. size all right so this is the implementation let's go ahead and run this method and and make sure that everything is fine all right also should return all students is green we can also add an extra test and make sure that for example this repository. find all was called only once so let's go ahead and test it just to make sure always that we have our application performing really well so here we have our repository and then times one and then dot find all to be called only one time let's rerun again all right so the the test is still green so now let's move on and let me tell you what we will be doing next all right now I want to give you another exercise and I want you to implement the test for this fine student by ID I'm pretty sure you're going to do it in a correct way and I will see you in the correction all right so as usual let's go back to our student service test. Java class and the first thing that we need to do is adding this test annotation and then creating a public void and let's call the method should find student by ID or should return student by ID all right so here always the given and here we have an INT student ID or an integer let's make it an integer student ID equals 1 and then let's create a student object we can also take it from here so let's call it student so here we have student student equals new student and then we have when so here we need to mock so here we have when we call our repository. findind by ID and then we pass our student ID and then I want to return an optional dot of my student all right and you might ask the question why I used optional because this find by ID is going to return an optional the second mock that we need to do we need to mock the two Student Response dto from this from the student mapper class and to return that one so from that we can just copy this one and then let's paste it in here so here we have when we make a call to our student mapper we are going to map this one and again we can just go up and copy this assertions so here I will create an object of type Student Response dto I will call it dto equals my student service do find by ID and then I will pass the student ID that I created and now we have the then so here we start the assertions so here we have our the dto do first name should be exactly the same one as the student. getet first name so here I will just copy the student from here and I will just replace it in here so now we can select all and here we have get and then let's make this one uppercase and now that's it also we can add another check we want to verify that our repository has has being called one time for the method find by ID so passing also the student ID as an object as a uh as a parameter and now let's go ahead and run this new test Method All right so we might miss something okay so here expected John example.com but the actual was john. mail.com so maybe let's fix it so here we have mail let's change this one also to mail and let's rerun again and the test is green and fine all right so that was it for this method let's move on and implement the next one that's good you really made a really good progress and I'm really proud of you so the next method that we need to implement the test for is find student by name and just I want to give you a quick hint you can Inspire from the previously implemented methods in order to implement it in a correct way so take your time and I will see you in the next lecture to provide you the solution for this exercise all right you did a good job now let's correct this exercise together and you might learn something new so as always we need to add the test annotation and then we have a public void and let's call the method should find student student by name all right so then what we need to do the first thing we can also copy things from what we have before so I'm going to explain it one by one so we can copy this part right here we can also copy this one right here so here we copi it so also let's copy it with a given so here the initialization of the students list and then we have the mock for the find all this one we will change later on and also we need to copy the mapping so let's go back here and now so when we call the find student by first name containing and here I just need also to declare a string student name let's call it John all right so here containing student name then return the students list and then when we call the student mapper do to Student Response dto of any student object I want also to return this mapped object or this Student Response dto now when I call so here let's use VAR just to make it shorter I will call it response dto equals our service do find all by name and here I need to pass the student name so then I need to do some assertions so I want to do assert equals that the students do size is equals to our response dto do size so this is what we need to do or what we need to check also we can add a verify that our repository has been called one time for the method find all by first name containing our student name so I'm going to break the line for this one and now let's run the test and check the result all right so the test is green and our method is correctly implemented all right that's good so now we still have only one method in our student service so let's go ahead and create an exercise for that and also we will see the solution together that was it for today's video I hope you learned how to test your applications how to test your services how to Mock and how to avoid injecting Real Spring boots services and dependencies into your your test classes so what I want to ask you now hit the Subscribe button smash the like button and help this video and help me grow this channel to reach more and more people and also the most important thing stay tuned for the next video because it it's real game changer and it will be something that you really like I've been working like for months on this video and now it's ready to be released thank you so much and see you next time
Info
Channel: Bouali Ali
Views: 7,200
Rating: undefined out of 5
Keywords: spring, mockito, testing, test, junit, software testing
Id: uGZQdD9IpQc
Channel Id: undefined
Length: 74min 11sec (4451 seconds)
Published: Tue Jan 02 2024
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.