XCTAssertEqual для пользовательских объектов в Swift

XCode 6, бета 5

У меня есть unit test, как это:

    func testMyObjectsEqual()
    {
        //....

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

XCTAssertEqualObjects больше не доступен в Swift, так как язык не делает различий между скалярами и объектами.

Итак, мы должны использовать XCTAssertEqual, что приводит к следующей ошибке:

 "Type MyObject does not conform to protocol Equatable"

Единственным обходным решением, которое я нашел, является наследование (MyObject) из NSObject, чтобы я мог сделать следующее:

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

Итак, мой вопрос: Есть ли способ (начиная с бета-версии 5) использовать XCTAssertEqual для пользовательских типов без необходимости полагаться на NSObject или перегружать все пользовательские типы с перегрузками "=="?

Ответы

Ответ 1

Если вы хотите сравнить ссылки в Swift, вы можете использовать оператор ===. Это то, что происходит при подклассе из NSObject (когда вы сравниваете объекты в Objective-C с помощью XCTAssertEqual, вы сравниваете ссылки).

Но это действительно то, что вы хотите?

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
}

Я думаю, что когда вы сравниваете пользовательские объекты, вы, вероятно, должны сделать их совместимыми с Equatable-протоколом и указать, когда ваши пользовательские объекты равны (в следующем случае объекты равны, если они имеют одинаковое имя):

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
}