Swift Unit Testing A ViewModel Basics: Mock & Protocol (Login | SwiftUI MVVM)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey everyone welcome to another video and in this video i'm going to show you how i would approach unit testing this login view model so we have our login view here and in our login view we have a state object view model and in the login view model it's pretty standard view model we have a bunch of properties describing the title subtitle placeholders etc then we have some published properties which are triggered for example when the person successfully logs in will trigger this success presented and that will trigger something in the view so at the moment we have this user service and if we go into our user service here we have the login method and you can see that it is using firebase directly inside the login method so if we were to write a test with this user service we would be reliant on firebase and this is not good because we're not actually testing the view model here we're testing firebase and what we actually want to do is isolate the view model and to do that we need to create a user service protocol so if we create a protocol here i'm going to call this user service protocol and inside the protocol we're going to have the exact same signature here and now we've got this protocol we can tell the user service to implement it and in our login view model we are going to swap out our concrete user service here and use the protocol and then we're going to inject our user service into our view model with this initializer and we're going to set the default argument to be user service so this will work in exactly the same way it just did but the advantage of doing this is that we can now inject our own user service protocol in our test and make sure this login function is behaving as we would expect it to so let's go to our unit testing target here and we're going to create a new test and we can use this template here unit test his class and i'm going to call this login view model spec and we'll create that there and it gives you a bunch of default methods here we're going to remove the last three and we're going to change this one to just be set up because we're not going to use the error there and now this setup will be called every time we run one of our tests so in our setup we want to basically initialize our view model so let's declare a var viewmodel login view model and we're going to force unwrap that but you'll notice that this can't actually see the login view model and in order to see the login view model we need to use a little trick at testable import and then we're going to import our unit testing mvvm which is here and this will mean that we can now see this internal type within our testing target so now that we can see our view model we can initialize it in our setup here so we're going to say dot init and what we want to do is basically inject a mock user service into our viewmodel here and then we can control how it behaves so let's go and create a new file and this is time it's going to be a swift file and i'm going to call it mock user service and this is going to be a final class mock user service and it's going to also implement the user service protocol and again we need to write this at testable import unit testing mvvm and then this compilation error will go away but it will tell us that we need to now implement that login function so let's do that and there's plenty of ways of doing this but just to save time i'm basically going to return a success so i'm going to return a success in our completion here and you can also test whether the email and password is correct but this is just one example of one test that you may want to implement now that we've written our mock user service we can inject it now so what we can do var mock user service and this is going to be a mock user service and we can create this in our setup and we can inject it into our viewmodel here and now the viewmodel will use our mock user service rather than the user service that is tied to firebase here so now that we're injecting our mock user service we can come underneath and we can write a test to see whether when there's a successful login it sets that success is presented to true so we can write test login with correct details sets success presented to true and there's plenty of ways that you might want to name this it depends on the style of your project and you might see things like underscores and slightly different ways of actually writing this naming but as long as you're following the convention that your team is using you should be good to go so inside our test here we are going to call our login so this is when they tap login we're sending this login action and after this login action we want to make sure that our success is presented is true so we can say x c t assert true view model dot success presented and if we just run this test now we should get a true result and there we go test succeeded now you might be thinking that this is pretty restrictive and what if we want to test the failure scenario so we can make our mock user service a little bit more dynamic by having a property here login result and this is going to be of type result void error and let's set it to success by default and instead of returning this success we're going to return this login result and now if we go back to our test here we can set this on our mock service like so and this will have no effect on this test but now if we want to test login with error sets error and maybe you can think of a better name for this but just to get the point across we're going to return a failure here and let's return a crude ns error for example sake and this time we're going to check to see whether our error set on our viewmodel so if we look at our viewmodel you can see here in the failure state we set the error on our viewmodel here so if we go back to our test and now we run our tests again we get two tests succeeding and just to show that this isn't passing every single time we will change these up and make sure that they can fail and there you go there's two failures and let's set them back and rerun again and you get two passes so this is just an introduction there's many more things to cover with unit testing so if you got some value at this video please do subscribe and give the video a thumbs up and i will see you for the next one
Info
Channel: James Haville
Views: 7,526
Rating: undefined out of 5
Keywords: unit testing, viewmodel, swift, swiftui, mvvm
Id: kHtEtAP4DNA
Channel Id: undefined
Length: 8min 39sec (519 seconds)
Published: Sun Nov 15 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.