Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift: overriding an initializer that takes an NSInvocation

I'm trying to create a reusable test harness in Swift with the idea that subclasses will extend the test harness to provide the instance under test, and can add their own subclass-specific test methods, something like this:

class FooTestHarness: XCTestCase {
  let instance: Foo

  init(instance: Foo) {
    self.instance = instance
  }

  func testFooBehavior() {
    XCTAssert(instance.doesFoo())
  }
}

class FooPrime: Foo {
  func doesFooPrime(): Bool { /* ... */ }
}

class FooPrimeTests: XCTestCase {

  init() {
    super.init(FooPrime())
  }

  func myInstance(): FooPrime {
    return instance as FooPrime
  }

  func testFooPrimeBehavior() {
    XCTAssert(myInstance().doesFooPrime())
  }

}

However, when XCode's testrunner tries to run FooPrimeTests, it doesn't call the no-arg init(), it calls init(invocation: NSInvocation!) (and fails because there isn't one). I tried to override this in FooTestHarness:

  init(invocation: NSInvocation!, instance: Foo) {
    self.instance = instance
    super.init(invocation)
  }

and in FooPrimeTests:

  init(invocation: NSInvocation!) {
    super.init(invocation, FooPrime())
  }

but this fails with the message 'NSInvocation' is unavailable.

Is there a workaround?

like image 878
David Moles Avatar asked Jun 30 '14 21:06

David Moles


1 Answers

I'm not os sure if I got it right, but checking the code you suggested you should get a compiler Error like: enter image description here

Which actually I reckon is quite normal since your FooPrimeTests is just subclassing XCTestCase which has got different init like:

init!(invocation: NSInvocation!)

init!(selector: Selector)

init()

Probably when you posted you're question you're running on an older version of Swift, (I'm currently running it on the Xcode Beta 6.2) that's why you can't see the error. But, and I say again if I got your point right, your class FooPrimeTests can't see you custom initializer just because is sublcassing XCTestCase, rather then FooTestHarness. Which is the class where the init(instance: Foo) is defined.

So you might probably want to define FooPrimeTests as subclass of FooTestHarness. That way you should be able to correctly see your initializer. Hope this help.

like image 164
DennyLou Avatar answered Sep 21 '22 13:09

DennyLou