Dependency Injection is a really important unit testing technique that makes your code better by exposing the dependencies very clearly. I wrote a blog post about dependency injection here. If you need to learn more about dependency injection, make sure to read it before moving forward with this post!

One big issue with dependency injection in Swift is that it often requires subclassing to work (see my previous blog post as an example). That conflicts with the ideal of using value types in Swift, since you can’t subclass a struct! So while I usually started out by making something a struct value type, I often ended up having to make it into a reference type so I could subclass it for dependency injection in my tests. It was really frustrating.

However, after this years WWDC session on Protocol-Oriented Programming (POP), I finally understand how to get rid of subclassing and still use dependency injection in my tests! The code is much better as a result 🙂

Before POP

So let’s take a look at the MinionService I had in my previous blog post on dependency injection:

Swift

1

2

3

4

5

6

7

8

9

10

11

12

13

14

classMinionService{

enumMinionDataResult{

caseSuccess([Minion])

caseFailure(NSError)

}

funcgetTheMinions(completionHandler:(MinionDataResult)->Void){

// pretend we're getting minions asynchronously

letminionData=[Minion(name:"Bob"),Minion(name:"Dave")]

completionHandler(MinionDataResult.Success(minionData))

}

}

The reason MinionService is a class is so I can over-ride the implementation of getTheMinions in my ViewController tests:

After POP

Using POP, since getTheMinions is the method I need to be able to have my own implementation of for testing, I can extract it out into a protocol and change my MinionService to a struct that conforms to that protocol!