Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

XCTAssertEqual for custom objects in Swift

XCode 6, Beta 5

I have a unit test like this:


    func testMyObjectsEqual()
    {
        //....

        XCTAssertEqual(myObject, myOtherObject, "\(myObject) and \(myOtherObject) should be equal")
    }

XCTAssertEqualObjects is no longer available in Swift since the language makes no distinction between scalars and objects.

So we have to use XCTAssertEqual which leads to the following error:

 "Type MyObject does not conform to protocol Equatable"

The only workaround I have found is to inherit (MyObject) from NSObject so that I can do the following:

 XCTAssert(myObject == myOtherObject, "\(myObject) and \(myOtherObject) should be equal")

So my question is: Is there a way (as of beta 5) to use XCTAssertEqual for custom types without having to rely on NSObject or littering all custom types with "==" overloads ?

like image 442
joakim Avatar asked Aug 16 '14 16:08

joakim


1 Answers

If you want to compare references in Swift, you can use === operator. This is what happens when you subclass from NSObject (when you are comparing objects in Objective-C using XCTAssertEqual, you are comparing references).

But is this really what you want?

class MyObject {
    var name: String

    init(name: String) {
        self.name = name
    }
}

func testMyObjectsEqual() {
    let myObject = MyObject(name: "obj1")
    let myOtherObject = MyObject(name: "obj1")
    let otherReferenceToMyFirstObject = myObject

    XCTAssert(myObject === myOtherObject) // fails
    XCTAssert(myObject === otherReferenceToMyFirstObject) // passes
}

I guess that when you are comparing custom objects, you probably should make them conform to the Equatable protocol and specify, when your custom objects are equal (in the following case the objects are equal when they have the same name):

class MyObject: Equatable {
    var name: String

    init(name: String) {
        self.name = name
    }
}

func ==(lhs: MyObject, rhs: MyObject) -> Bool {
    return lhs.name == rhs.name
}

func testMyObjectsEqual()
{
    let myObject = MyObject(name: "obj1")
    let myOtherObject = MyObject(name: "obj1")

    XCTAssertEqual(myObject, myOtherObject) // passes
}
like image 172
Marián Černý Avatar answered Sep 17 '22 17:09

Marián Černý