Unit Testing Optionals In Swift: The XCTAssertNotNil Catch

Recently I pointed out a better way to test optionals using XCTAssertNotNil. So as I’ve been writing a lot more tests recently, I decided to try this way out. But I soon ran into a problem:

OptionalsTesting

The error message here is “‘PROJECTNAME’ does not implement methodSignatureForSelector: — trouble ahead”. After wrecking my head for a while, I came across this blogpost.

Turns out, this is happening because my Minion class is NOT a subclass of NSObject. Once, I imported Foundation and subclasses my Minion from NSObject, the problem disappeared:

MinionClass

XCTAssertNotNil also doesn’t work if I choose to make the Minion a struct instead of a class:

XCTestStructSwift

I’m not a fan of adding extra code to my classes (or making something a class vs a struct) for the sake of testing, so I think I’ll be switching back to the unwrapping my optionals in tests at least for my own classes that do not derive from NSObject…

OptionalTesting

Looking forward to Apple improving XCTest to work better with Swift!

Enjoy the article? Join over 14,500+ Swift developers and enthusiasts who get my weekly updates.

  • Another way to think about this is that it’s not necessary to assert that an optional value is not nil–just handle both cases in the code. If the value is nil (Optional.None), you do nothing or return nil from your function; if it’s not nil, you go ahead with your normal logic. So just keep ‘passing the buck’ onwards through as much of your code as possible.

    Of course, part of your normal app logic may be to do something specific when some value is nil. In that case your last block of code above is a perfect template for that, minus the XCTest assertions.

  • Just used this today – I’m surprised this still hasn’t been improved with Swift 1.2. Thanks, Natasha!

    • Because of this, I happily use hasValue from another post of Erica:

      // http://owensd.io/2015/05/12/optionals-if-let.html
      func hasValue(value: T?) -> Bool {
      switch (value) {
      case .Some(_): return true
      case .None: return false
      }
      }

      // ...
      XCTAssert(hasValue(optionalMinions))
      if let minions = optionalMinions { ... }

  • benrudhart

    XCTAssertNotNil can be used with optionals in Swift 2!

    • Looks like there are a few improvements in Swift 2 – you don’t have to subclass from NSObject anymore, so that’s nice! But it doesn’t work with structs.