Swift: XCTest Class 'FirstDemoTests' has no initializers
Asked Answered
D

3

10

I have the following code (trying to avoid implicit unwrapping):

class MyTests: XCTestCase {

    var viewController: ViewController

}

But I'm getting the following error:

Class 'MyTests' has no initializers

I fixed with this:

class MyTests: XCTestCase {

    var viewController: ViewController

    override init() {
        self.viewController = ViewController()
        super.init()
    }
}

Would be a issue using init() in XCTest class?
I'm using Swift 4, Xcode 9.2.

Domiciliary answered 14/2, 2018 at 22:22 Comment(0)
Q
22

I understand that you'd like to avoid implicitly unwrapping, but unfortunately (unless you want to go through the trouble of writing your own test runner), you don't have control over which initializer is called when the tests are run.

You could get around this by implicitly unwrapping, as you know, and setting the value of the property in setUp(), which gets called before every test, so you can be sure the property will not be nil during your tests. This is relatively safe.

class MyTests: XCTestCase {

    var viewController: ViewController!

    override function setUp() {
        super.setUp()
        self.viewController = ViewController()
    }
}

Alternatively, you could make the property lazy, which means that it does not have to be implicitly unwrapped. This means that the property does not have to be initialized during object initialization so you don't need to write a new initializer, but will be initialized the first time it is accessed.

class MyTests: XCTestCase {

    lazy var viewController: ViewController = {
        return ViewController()
    }()
}
Quixotic answered 16/2, 2018 at 7:44 Comment(0)
N
2

When writing XCTest then no need of writing initializer.

XCTestCase providing method to prepare test items before execution of actual test.

Declare viewController as explicitly unwrapped(to avoid implicit unwrapping) as below.

class MyTests: XCTestCase {

    var viewController: ViewController!

}

Overrider below 2 methods always in your each XCTestCase class.

setUp is to prepare variables before actual test execution. Initialize viewController in setUp.

override func setUp() {
        super.setUp()
        self.viewController = ViewController()
        // Put setup code here. This method is called before the invocation of each test method in the class.
    }

tearDown is to release variables and other resources after finishing test. Release viewController in tearDown.

override func tearDown() {
        // Put teardown code here. This method is called after the invocation of each test method in the class
        self.viewController = nil
        super.tearDown()
    }
Nashua answered 15/2, 2018 at 12:38 Comment(1)
Great answer, I'd just remove the "Put setup code here" leftover Apple comment.Thrush
C
0

Actually, setup() called in every test method invocation.

/*!
 * @method -setUp
 * Setup method called before the invocation of each test method in the class.
 */
- (void)setUp;

So, why do u need to create viewController, let's say, 3 times for 3 test methods in the current XCTests subclass? You can try to declare your variables outside XCTests subclass

Capitulate answered 13/11, 2018 at 13:31 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.