I recently read an article in objective-c using the control swizzling test Uialertcontroller. Such articles have always prompted me to find a way to test the same thing without using control swizzling. Although, I know swizzling is a very powerful tool for developers, but I personally try to avoid using it. In fact, in the last six years, I have only used swizzling in one application. So I believe we can now implement the test without using swizzling.
So the question is, how do you not use swizzling in Swift to test Uialertcontroller?
Let's start with the code we want to test. I have added a button to the Storyboard. (I used Storyboard to have a more intuitive feel for the little partners who didn't want to write the code interface) when you press this button, a window (alert) appears with a caption, message content, and two buttons, OK and Cancel (cancel).
Here's the code:
Import Uikit
class Viewcontroller:uiviewcontroller {
var actionstring:string?
@IBAction func Showalert (Sender:uibutton) {let
Alertviewcontroller = Uialertcontroller (title: "Test title", Message: "Message", Preferredstyle:. Alert) Let
okaction = uialertaction (title: "OK", style:. Default) {(action)-> Void in
self.actionstring = ' OK '
} let
cancelaction = uialertaction (title: "Cancel" , style:. Cancel) {(action)-> Void in
self.actionstring = "Cancel"
}
alertviewcontroller.addaction ( cancelaction)
alertviewcontroller.addaction (okaction)
Presentviewcontroller (Alertviewcontroller, Animated:true, Completion:nil)
}
}
Note that in this example the pop-up action does not do anything specific, they only indicate that they can verify the unit test.
Let's start with a simple test: Test the title and message content of the window controller.
The code for the test is as follows:
Import xctest
@testable import testingalertexperiment
class Testingalertexperimenttests:xctestcase {
var sut:viewcontroller!
Override Func SetUp () {
super.setup ()
sut = uistoryboard (name: "Main", Bundle:nil). Instantiateinitialviewcontroller () as! Viewcontroller
uiapplication.sharedapplication (). Keywindow? Rootviewcontroller = Sut
}
override Func teardown () {
//Put teardown code here. This are called after the invocation of the all test method in the class.
Super.teardown ()
}
}
' '
We need to set the SUT as the root view controller, otherwise the view controller cannot eject the pop-up view controller.
The code to add the Uialertcontroller test title is as follows:
"Swift
func testalert_hastitle () {Sut.showalert (
UIButton ())
xctasserttrue ( Sut.presentedviewcontroller is Uialertcontroller)
xctassertequal (Sut.presentedviewcontroller?. Title, "Test Title")
}
It's simple. Now let's test the Uialertcontroller Cancel button. There is a problem: the closure of the window action cannot be obtained. So we need to simulate the window action, in order to store the handler and call it in the test to see if the window action is the same as we expected. Add a class to the test case:
' Swift
class Mockalertaction:uialertaction {
Typealias Handler = ((uialertaction)-> Void)
var Handler:handler?
var mocktitle:string?
var mockstyle:uialertactionstyle
convenience init (title:string, Style:uialertactionstyle, Handler: ( uialertaction)-> Void)? {
self.init ()
mocktitle = title
Mockstyle = style
Self.handler = Handler
}
override Init () {
Mockstyle =. Default
super.init ()
}
}
The main task of this simulation class is to capture handler blocks for later use. Now we need to insert this mock class into the implementation code. Replace the code in the view controller with the following:
Import Uikit
class Viewcontroller:uiviewcontroller {
var Action = uialertaction.self
var actionstring: String?
@IBAction func Showalert (Sender:uibutton) {let
Alertviewcontroller = Uialertcontroller (title: "Test title", Message: "Message", Preferredstyle:. Alert) Let
okaction = action.init (title: "OK", style:. Default) {(action)-> Void
in self.actionstring = ' OK '
} let
cancelaction = action.init (title: "Cancel", s Tyle:. Cancel) {(action)-> Void in
self.actionstring = "Cancel"
}
alertviewcontroller.addaction ( cancelaction)
alertviewcontroller.addaction (okaction)
Presentviewcontroller (Alertviewcontroller, Animated:true, Completion:nil)
}
}
' '
We added a class variable ' Action ' and set it to ' uialertaction.self '. This variable we will use when initializing the window action. This allows us to rewrite it when we test it. Like this:
"Swift
func testalert_firstactionstorescancel () {
sut. Action = mockalertaction.self
Sut.showalert (UIButton ()) let
Alertcontroller = Sut.presentedviewcontroller as ! Uialertcontroller let
action = AlertController.actions.first as! Mockalertaction
action.handler! ( Action)
xctassertequal (sut.actionstring, "Cancel")
}
First we inserted the window action. Then we call the Code pop-up view controller. We obtained the cancellation action from the rendered view controller and successfully invoked the captured handler block. The final step is to assert whether the current action is the same as we expected.
That's it, a simple way to test uialertviewcontroller without using swizzling.
The above is a method of testing Uialertcontroller in Swift, and I hope it will be useful to you.