How To Test UIAlertController in Swift
Update Nov. 25th 2015: This kind of testing does not work. You can find the correct version here.
Recently I read a blog
post about
testing UIAlertController
in
Objective-C using control swizzling. Posts like this always trigger me
to find a way to test the same without the swizzling. I know that
swizzling is a powerful tool developers should have access to in their
developer tool box. But I personally avoid it when ever I can. In fact
only one app I worked on in the last six years used swizzling. And today
I believe we could have implemented it without it.
So how to test UIAlertController
in
Swift without the swizzling?
Let’s start with the code we want to test. I have added a button to the storyboard. (I’m using a storyboard here to make this post accessible to people who don’t wan’t to do their UI in code.) When the button is tapped an alert is shown with a title, a message and two buttons, OK and Cancel. Here is the code:
Note that the alert actions don’t do anything interesting in this example. They just represent a change a unit test could verify.
Let’s start with an easy test: Test the title and the message of the alert controller.
The setup code for the tests looks like this:
We need to set the sut to the rootViewController otherwise the view controller can’t present the alert view controller.
Add the following test for the title of a UIAlertController:
That was easy. Now let’s test the cancel button of the UIAlertController. The problem: The handler block of the alert action can’t be accessed. Therefore we need a mock alert action to store the handler to be able to call it in the test to see if the action does what we expect. Add the following mock class within the test case:
The primary job of the mock class is to capture the handler for later use. Now we need to inject the mock class into the implementation code. Replace the view controller code with the following:
We have added a class variable Action
which is set
to UIAlertAction.self
.
This variable is used when we initialize the alert actions. This enables
us to overwrite it in the test. Let’s do it:
First we inject the mock alert action. Then we call the code that presents the alert view controller. We get the cancel action from the presented view controller and call the captured handler. The last step is to assert that the action actually does what we expect.
That’s it. A very easy way to test an UIAlertViewController
without the
swizzling.
Update Nov. 25th 2015: This kind of testing does not work. You can find the correct version here.