Using dependency injection to test an UIViewController

Rodrigo Cavalcante
Cocoa Academy
Published in
3 min readMay 7, 2018

Hi everyone, is it very common when we start coding to create objects that needs others objects to work e.g. in a Car class that need a Person object to start the engine and drives ( starEngine and drive are hypothetical methods that needs a Person instance). So we can say that a Car needs a Person to work.

The code above shows us that Jhon is driving our car, and only Jhon can do it! Because every Car object will create an instance of a Person named Jhon. But what if Mary wants to drive? How can we rewrite that code to let Mary drive our car?

We can pass a Person to our Car, making it work for any instance of Person, in other words: reusable. We don't care how our Person object is created, if it's created by a factory, another class or if it needs a name, age or any other dependency, we just need a Person instance.

In software engineering, dependency injection is a technique whereby one object (or static method) supplies the dependencies of another object. A dependency is an object that can be used (a service). An injection is the passing of a dependency to a dependent object (a client) that would use it.

Let's turn this example in a daily problem. In the code below, our ViewController uses a ListService object. This ListService loads data from a web service but what if we want to load data from a local database, a file or somewhere else? Do we need to create another ViewController ? And if we want to test this ViewController how can we make the API response's to be always the same so we can validate our test?

Now think about testing this class we'll need at least an internet connection and a stable response every time we run our tests. This makes our test slow and impracticable. The solution in to use dependency injection to use a custom mocked ListService object.

One way to do that is to create an interface that has a load method and implement it in custom objects. In other words, we create a Service protocol and objects that know how to load data from web servers, database, files, etc.

With this approach, we can easily create different kinds of Service to use. E.g. one service loads data from a web service, the second one from a local database and the last one is mocked so we can use it for testing our ViewController without the need of a real API response or data in our local database.

Every kind of Service object can have unique dependencies. Our WebServiceListService will need to know how to make a request, so it will need a Request object. DataBaseListService needs a database connection to load data. Theses unique dependencies are invisible to our ViewController . It just needs a Service object that has a load() method.

To test our ViewController we just need to create a MockListService and inject it during our tests.

Injecting objects makes our code decoupled and easier to be tested. This can be achieved by passing objects via constructors, setters or interfaces.

Ps: If you like this post, share it on twitter, recommend it on medium, or both =). This really helps me to reach more people. Thanks a lot.

--

--