Quick Tip: Test functions with DI
29 Nov 2016Testing your code’s collaborators is really important but how do you test functions like UIImage(named:)
or NSLocalizedString(_:tableName:bundle:value:comment:)
?
#What are we testing?
We are not interested in testing whether methods like UIImage(named:)
actually work as that’s Apple’s job but we should verify that we invoke the functions with the correct arguments.
Take the following example
The above is a simple call to UIImage(named:)
with some simple logic to build the image name based on the passed index. The thing that we need to test here is the image name construction logic - we would like our tests to verify that if we call the function with the input of 1
that it will invoke UIImage(named: "jump_001")
.
#Dependency Injection to the rescue
To create a seam that allows testing the collaborator we can make UIImage(named:)
injectable. Our production code can continue to use UIImage(named:)
but our tests can use a different function that allows us to capture and verify the input.
####Start by making it injectable with a sensible default
In the above we made a couple of changes
- Added a new variable of type
(named: String) -> UIImage?
that holds our image loading function - Invoke
loadImage(named:)
instead of directly invokingUIImage(named:)
####End by adding some tests
Now that we have done the scaffolding we can add tests that verify that the correct arguments are provided when loading images
#Conclusion
The fact that functions are a first-class type in Swift means that it is super simple to use dependency injection to enable testing of functions. It’s always important to test our code’s collaborators to ensure that we are calling their contracts correctly and with the arguments that we expect to send.