Introduction to Mocking in iOS Using Swift

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello everyone and welcome to other Shar weekly in this video I like to go over what exactly is mocking in unit testing so the idea of Mark is that you are simulating the real object so why would you ever want to do that why would you not just use the real object well there are some conditions like your application your test is dependent on some third parties maybe it's a service maybe I am its own service maybe it's a pedometer that has to be run on a real device and you are testing those things you're testing the either the unit test which should run in a memory or you're testing the UI test just like UI portion of the test that has nothing to do with fetching data or running it on the actual device alright so in those cases you can use marking and you can walk out the third party so let's take a look at this example this is our very very very simple application you can see that I have written a UI test and the test simply says when the user logs in successfully then display user information on the screen and we are going to be writing something in the user name text field password text field we will go ahead and click on the login button and then if the login is successful then on the same exact V we have a company label and a name label which is going to be populated with ABC Inc for the company name and John Doe for the name and this is actually going to make a call to a rep service so let me actually show you the web service it is written in the node using JavaScript you can see nothing really interesting going on it's simply going to return John Doe name is John Doe company's ABC so it's all hard for the data but we are going to invoke that so if I go ahead and run this test and right now make sure that you understand that I am actually connected to the internet I'm running my UI test and this is actually going to go and invoke the actual service so it is going to make a actual web request using URL sessions or share or whatever and you can see that I'm writing a and all the things and the tents actually pass it's great so this is working this is my UI test now let's see if I am maybe stepping in to a plane or I am trying to run this tenth of the doubt internet connection so you can see over here that I'm no longer connected to the Internet so I'm gonna go ahead and run the same exact tents but without internet connection all right so let's see if this tents actually passives or this test fails so if you run the test we're gonna fill out the username and fill out the password and press the login button and we are hoping to get back the company name but we did not and it actually failed and the things that you should notice over here is that we did not get anything back now this is not an acceptance test this is not an integration test this is a UI test so our UI test why is it dependent on the web service or the internet that's a bad test it has a dependency on the web connection or the Wi-Fi connection so that is where we will mock out that dependency mock out means whenever it's going to go and hit the API or web service that it's supposed to return the information like company label or a company name and user person name we are going to mock it out meaning we're going to give you some predefined response so how can we do that well the first thing you will notice is that this is our HTTP client which in which is our in our main application which is called authenticate function and it actually goes to the URL a real service and gets all that information and the person who is using the HTTP client is the login view model you can see over here that in order to create the login view model we have to pass an HTTP client so we have to overcome this step because this is a concrete implementation of HTTP client we should be able to pass in a simulation object over here a mocked object I'm not service that can return a response maybe by reading a file and that can work without the web connection a Wi-Fi connection so the first thing I'm going to do is I'm going to go to the services and I'm going to add a new file over here and what we're going to do is we're going to create a protocol so I'm gonna go ahead and say we're here HTTP client protocol alright and I'm gonna go ahead and create that so this will be the protocol it's going to be called HTTP client protocol if you want to create an HTTP client then you must conform to this protocol what kind of function we will have in this protocol well I can get the name of the function actually from here this will be the name of the function or this will be the definition of the function so anybody who wants to be interested in becoming the HTTP client must use this particular protocol let's go ahead and build that application right now and what we're going to do is we're going to make sure that the HTTP client conforms to this protocol so we can say HTTP client protocol right here let's go ahead and build that there's worse of working correctly that's fine and now we can go to login view model and we can see that in the login view model we are hard-coding it to a concrete implementation of HTTP client so I'm gonna go ahead and change this to actually be client protocol so the person has to pass an HTTP client protocol okay great this means that anybody who is conforming to HTTP client protocol can be passed to a login view model and this is our opportunity to pass in a mock client all right so for the more client I'm gonna go back to the mocked UI test because marks are part of the test so that's why I'm gonna create the mocking objects in the in the test and now we can go ahead and create our more client so let's go ahead and add a surf file and I can go ahead and say over here mock HTTP client so I've added a new file and I'm calling eight mark httpclient it doesn't really have anything so first of all I'm gonna go ahead and import foundation and since I want to use the HTTP client protocol which is actually defined in a completely different project I can import using testable import so let's go ahead and say testable import and that particular project is called introduction to marking now I can go ahead and create my mock HTTP client this is going to be conforming to the HTTP client protocol that's a beauty of the mock object and creating a protocol that now we can conform to that I'm going to go ahead and copy this function because we there is only one function that I need to conform to or implement and there we go great now authenticate function since we are defining it in the mortgage CB client it will have a different definition because instead of going to the actual service going to the Wi-Fi connection and invoking an actual JSON API it is going to be reading it from a file or a we can hard code it if you want now I'm going to read from a file and the reason I'm going to read from a file is simple because I want it to be as close to the real thing as possible alright so the first thing we need is some sort of a file so I'm gonna go over here and I'm going to go ahead and add a new group and yeah I can simply say over here JSON responses because it is kind of like a response that we are getting right so I'm calling it JSON responses and in the JSON responses I can add any kind of a response so I can say over here new file and we're just going to add like a simple HTTP empty file is fine I guess and we can say authentication successful response or odd success response that's perfectly fine or success response dot JSON and this file will have the actual successful JSON response what does the successful JSON response looks like well we have the service which is running the actual URL if we pass in or go to the login it's going to return us some sort of a JSON response which kind of looks like that so that is something that we can go ahead and paste it and that's the response that we are actually expecting so I'm just pasting it over here and if it sounds about right right now inside the mock object so mark Ashley big line we can go ahead and read that particular response file we can also decode it and send the actual response so how do we do that well the first thing we need is to get to the actual URL so URL equals to bundle and when you are trying to read it inside some sort of a unit testing we have to use a four and we have to give it some access to some sort of a file so that it knows that we are trying to read it from the unit testing bundle and we're not trying to read it from the main bundle so that's why I'm telling it that well make sure that you find the class called mock HTTP client all right don't you RL and for a particular resource so what will be the resource well in this case the resource is a new pot and then success response and the extension of the resource is actually JSON there we go okay now we will get some different things for more here we are going to get a data so data equals two data and we are going to get contents of the URL where we can pass in the URL else if this is not working then we can go ahead and simply fire the completion block firing it and returning mail okay so instead of going to the actual URL and you know fetching all that information what we are doing is we are simply using our response file which have hard-coded response which we know it will work and now we can go ahead and get the actual response response equals to try and we are going to perform JSON decoder dot decode and we are going to decode it to user dot self because the response that we have added that will and should map to user dot cell for user object and we can pass in the actual data if it's going to return us some sort of a user so we can just say user over here that's fine also there we go okay and we can simply fire the completion at this point by passing in the user object if you go and check out the user object that is actually in the original project or the main application they use an object simply the decodable which has user name name and company so nothing more complicated going on over there but you can see that how the mortgage DB client is different from the real client so if you look at the real client it's literally going to the URL making the request but the markets Arabic line we are writing is reading from a file which will always exist so that's the difference now you can run this without having to connect to the internet all right okay so we have this now ma client which is great but how will I test or how will we tell our test that we are using the mock HTTP client and we are not using the original client if you go and open up content view this is where we are actually creating the object itself you can see on line number 16 this is actually troublesome we are hard coding it that we'll be using the HTTP client so how can we replace that with the mock client now this is going to be a little bit more interesting because we will have to switch meaning when we are creating a login view model and if the code is getting invoked from a the test the UI test then we will we should replace the Asha to be climbed with the mock crime but if we are not running it from a test then well it should be using the actual client which is e as should we be client now if I go ahead and over here I can say mark HTTP client and then this is not good because this is the actual code the actual application that you're typing and now every time even in the real app it is going to be using mark as should be quiet so you can't do that that's not good practice right it has to be flexible to switch itself if we are running it from a test then you should use a marquetry to be fine if you're running it just the app on your device on production it should use HTTP client but the question is how do we make sure that it actually switches so let's go ahead and see how we can do that so the answer to this is that we will have to create a factory or some sort of code that can predict that can assume that if it's running on a or through the test then it will return a mock HTTP client and if it is running on a real app then it should just return HTTP client so I'm going to go ahead and create a new group and I'm gonna call this factories and inside the factory I'm going to go ahead and add a new file so if file it fine and I'm gonna go ahead and say HTTP client factory you can obviously name it anything that you want but since this particular class is responsible for creating it should it be claimed as that's why I'm calling it a factory using the factory pattern and now we can go ahead and maybe create a static function so function static and we can call it create that's fine it is going to return us something which is using HTTP client protocol Pro to all okay now a couple of different things going on over here I think I always misplace when I'm creating the static function so I think it should be like that and we should be returning HTTP client protocol now if I go ahead and return HTTP client over here then it means that it is always going to return me the real issue to be client not the mock one and it's again going to try to invoke the web service which which we don't want so somehow we need to check over here that if the thing is running or if the environment is UI test then we can return something else now how do we check well let's go ahead and we're going to use something called the environment arguments that you can pass in so inside your UI test when we are running the test we can set the environment so amp dot and you can see over here you can set the launch environment and this is simply a dictionary so you can pass anything that you want I'm just gonna pass in env and I'm gonna call call it test all right this means that whenever we run this application whenever we launch this application the launch arguments or the environment will have a key called environment and the value will be text now this is fine and this is only going to be passed when you are actually using or running it through the test so we need to access that value right over here so in order to access the launch environments you can use the process info dot environment and this is going to return you a dictionary so let's go ahead and get that over here and what I'm going to do is I'm simply going to go ahead and print that out and so you can see all the different launch arguments when we are using the process info and process info and you'll also see that there are a lot more launch arguments that are passed by default now we can go back to our content view and instead of using the HTTP protocol I'm going to now use the STD he the factory and not create so based on well right now it's just going to return here should it be climb but if I run this actual app or from the actual test over here hopefully we'll be able to see some sort of launch arguments being displayed so and then we'll see that if the argument our E and V is found over there then we can go ahead and we can get that so let's go ahead and run our test okay so test is already failing for some weird reason well let's go ahead and first fix that stuff so we have a lot of errors going on over here I don't think that is a correct error so let's go ahead and try to find out that what exactly is going on all right everyone so I try my best but I am NOT able to find the problem and these errors it looks like they are coming from the actual self compiler for some reason it is just throwing these rear errors you can see over here that these errors doesn't really mean much I mean they're saying undefined symbol protocol descriptor for introduction to mocking HTTP protocol but when you go to the mock client we are actually using the testable imports and that is where the HTTP protocol actually lives so it should be able to use it in the other project that I did I was able to use it but something got bad for this particular project and I definitely don't know what exactly is going on so we're gonna continue with it hopefully you are not going to face that problem if you actually do face this exact problem these kind of errors let me actually show you right here then try to find a solution and if you do find the solution let me know and I'll try to implement the update for this video all right okay so this is our mocked HTTP client and you can see that it is reading from the JSON file which is odd success if I look at the JSON file I can I've added it to the introduction to mocking project also so to friend targets that's fine and inside the factory what I have done is that we are reading the environment value EMV which you can see that I am setting it right over here in the test env environment is test so when it is running from the test it's going to launch the actual app and then we are using if I go to the content view we're using the over here so we have to use the correct one the actual factory so I can go ahead and say HTTP twine factory dot create and if you jump into the create function you can see HTTP client factory is entered is that some other thing that's kind of weird that it actually popped out o create so let's go to the create manage buffer or create I don't know where that is coming from unless I have created a completely different name maybe that's the reason that is possible I don't think there is anything called HTTP client factory I mean we can definitely check in the documentation so let's go to the documentation and we will check that if this particular factory or actually be client factory if that is something that to be considered so if we go to developer documentation right here let's search for this actually we client factory ok so there's nothing like that so that's not the issue ok so inside the HTTP client factory we are using the process info environment variable and if the environment variable is test that we are returning the mock HTTP client and if it is not then we are returning the HTTP client all right but unfortunately for me it is definitely not working right so if I run the app from the test which is from over here if I run the test it's completely failing it's not even building correctly and I personally don't know what exactly is wrong with this the errors are not really making sense to me that what exactly is going on maybe this is a bug in sort of compiler or maybe I'm doing something wrong but it's trying to say that well user has been reference and it doesn't really know what user is which doesn't really make sense because we are inside this file and I can go ahead and also import let's go ahead and do a testable import and I will import the introduction to mocking project but let's go ahead and run it now nope still the same issue you can see that in the mock HTTP client I'm already importing the introduction to mocking which is our main project but it's still not working hopefully it will work on your scenario because I have a separate project that is exactly the same and it works over there so something either I messed up or something is just not timing out to be right and the IFS I think it's just that maybe I made a mistake some time earlier but even with cleaning the product or cleaning the bill folder clean the bill folder and removing the drive data it's not really picking up correctly so anytime I run the test or if I try to run the test it is definitely giving me these problems so if I run the test you'll see that's always giving me those issues so something is going wrong I don't know what it is so hopefully if you find the problem you'll let me know and I will be able to update those things all right so hope you have enjoyed this video I mean I think 95% of the things we did will be the same I think that 5% where you're looking at the bug that is where we kind of messed up and that is where we I don't have the answer of why we are getting this kind of a bug every time we use the HT or mocked HTTP client which is using the HTTP client protocol defined already over here all right so hopefully you'll let me know if you find the issue or if you find the solution and I will update the video to reflect that part if you want to horde my channel then the best way would be to go to unity and check out my many different courses you can see that I have a course on safety why and this is a very you know long course it's a 15 hour course so I have covered pretty much all the different scenarios that you are going to be finding out but if you want to check out my other course simply click on the name and you can see that I have many other courses including a course on machine learning using artificial intelligent that's a brand new course that have been released and I'm also working on a course on unit testing which is going to dive into more of unit testing if you are looking for course on a arcade I have a course on air Kate I have a course on flutter and you can see the course I mean I have a huge list of courses that I have that you can utilize alright so thank you so much for watching this video and once again if you find a solution for the problem that I was facing I'll definitely appreciate it I wasn't able to find anything that will fix the problem but if you do find the problem definitely let me know and I will update the video to reflect that thank you so much and I hope you enjoy the video
Info
Channel: azamsharp
Views: 4,013
Rating: undefined out of 5
Keywords: ios development, swift language, mocking ios, mocking swift, unit testing, testing ios, swiftui tutorial, how to learn ios development, learn ios development, ios development with swift
Id: KyopZ0etsAE
Channel Id: undefined
Length: 25min 44sec (1544 seconds)
Published: Sun Apr 26 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.