Testing Swift Protocol Delegates

I ran into an interesting problem when trying to test that a delegate was set. Here’s a simplified example:

protocol MyProtocol {
  func myMethod()
}

class ClassWithDelegate {
  var delegate: MyProtocol?
  ...
}

class ClassUnderTest: MyProtocol {
  var otherClass: ClassWithDelegate

  init() {
    self.otherClass = ClassWithDelegate()
    self.otherClass.delegate = self
  }
}

In order to test that our ClassUnderTest is instantiating the ClassWithDelegate and setting its delegate, we could do the following:

class OurTests: XCTestCase {
  var testClass: ClassUnderTest()

  ...

  func testThatOtherClassCreated {
    XCTAssertNotNil(testClass.otherClass)
  }

  func testThatOtherClassDelegateSet {
    XCTAssertTrue(testClass.otherClass.delegate === testClass)
  }
}

This looks pretty simple, right? For those of us still learning Swift, it isn’t simple. What happens is that the compiler refuses to build, with the error: ‘MyProtocol’ is not identical to ‘AnyObject’.

After tons of reading, and learning a lot about Swift protocols and pointers, I basically stumbled upon the solution: add the “class” keyword to the protocol. This tells the compiler that only objects will implement the protocol, not structs. It then is quite happy to perform tests for nil and/or identicalness (?). So the working protocol definition looks like this:

protocol MyProtocol : class {
  func myMethod()
}

Now all the other code works.

One thought on “Testing Swift Protocol Delegates

Leave a Reply