First, to abstract CLLocation, we will define a protocol with only the variables or functions that we need for our code.

Now, we can get a location without CoreLocation. So if we analyze the ViewController, we can see that we do not really need a CLLocationManager, only someone who provides us with the user’s location when we request it. Therefore, we will create a protocol that contains our needs and whoever conforms this protocol could be the provider.

In our case, we have created UserLocationProvider. This protocol specifies that we only need a method to request the user’s location and the result will be through the callbacks that we provide.

We are ready to create a UserLocationService, who conforms that protocol and who provides us the location. By this way, we have solved the dependency with CoreLocation in our class, but wait… UserLocationService needs request the location by CLLocationManager…so, it seems the problem has not been solved yet 😅

Protocols to the rescue again, simply create a new protocol to specify what is a location provider for us:

We have extended the CLLocationManager functionality, conforming our new protocol.

Now yes, we are ready to create the UserLocationService 🎉, it would look like this:

UserLocationService has his location provider, but he will not know who he is, for him it does not matter, he only needs the user’s location when he requests it, the rest is not his responsibility.

The extension to conform CLLocationManagerDelegate protocol, is needed because we are going to use CoreLocation. But how we will see in the tests, we don’t really need it to verify that our class works fine.

We could add any kind of delegate inside the protocol, but for this example it’s too much, I think 🙂

Before to start with the tests, let’s see how our ViewController looks like using UserLocationProvider instead of CLLocationManager.

Looking this code, we conclude that now, our ViewController, has less code, fewer responsibilities and is more testable.

Tests

Let’s go with the tests. Firstly, we are going to create some mock classes that we need to test our ViewController.

Using these mocks, who we can inject whatever results we need, we will simulate how an UserLocationProvider works. So we will put focus in our real target, the ViewController.

We have created two tests, one checking if we don’t have authorization to request the location, the provider doesn’t provide anything. And another one, the opposite case, if we are authorized, we should obtain the user’s location. And as you can see, the tests are passed!! ✅ 💪

Besides the ViewController, we have created an additional class, UserLocationService, so we should cover him as well.

LocationProvider needs to be mocked, since it’s not the target of this test.

A lot of tests could be created, but verify if the provider says that we have authorization, if not request it and otherwise we request the location, could be one of them.

Conclusion

As you can imagine, there are many ways to decouple your code and this publication is only one of them. But I think it could be a good example to show that testing is not a difficult task.

If you remember the image in the top, you can see LEGO bricks, it’s why I think they explain very well what is decouple and abstract your components. At the end it's defined to a specific way to connect them, but, the color does not matter.

Perhaps one of most lazy tasks is creating the mocks, but for that already there are libraries and tools and facilitate this work, like Sourcery. Also, here is an article by my workmate, Hugo Peral, explaining how use Sourcery to save time doing tests. Or this one by John Sundell, it gives more details about how make mocks.

Nothing else, thanks for reading this publication. Share it if it was useful for you or if you think could be useful for someone 😉. Feel free to comment below if you have any doubts or any suggestion of improvement.