Testing for equality in Realm

前端 未结 2 1288
星月不相逢
星月不相逢 2020-12-03 23:19

I\'m trying to test for equality among Realm objects in unit tests. However, I\'m unable to get objects to return true for their equality.

相关标签:
2条回答
  • 2020-12-03 23:46

    Katsumi from Realm here. Realm object's Equatable is implemented as follows:

    BOOL RLMObjectBaseAreEqual(RLMObjectBase *o1, RLMObjectBase *o2) {
        // if not the correct types throw
        if ((o1 && ![o1 isKindOfClass:RLMObjectBase.class]) || (o2 && ![o2 isKindOfClass:RLMObjectBase.class])) {
            @throw RLMException(@"Can only compare objects of class RLMObjectBase");
        }
        // if identical object (or both are nil)
        if (o1 == o2) {
            return YES;
        }
        // if one is nil
        if (o1 == nil || o2 == nil) {
            return NO;
        }
        // if not in realm or differing realms
        if (o1->_realm == nil || o1->_realm != o2->_realm) {
            return NO;
        }
        // if either are detached
        if (!o1->_row.is_attached() || !o2->_row.is_attached()) {
            return NO;
        }
        // if table and index are the same
        return o1->_row.get_table() == o2->_row.get_table()
            && o1->_row.get_index() == o2->_row.get_index();
    }
    

    In summary, a) if both objects are unmanaged, it works same as normal object's Equatable. b) if both objects are managed, if they are the same table (class) and index, they are equal. c) If one is managed, another is unmanaged, ther are not equal.

    "managed" means the object has stored in Realm.

    So a and b in your code is not equal. Because a and b are unmanaged (have not stored in Realm) and they are different objects.

    let a = Blurb()
    a.text = "asdf"
    let b = Blurb()
    b.text = "asdf"
    XCTAssertEqual(a.text, b.text)
    

    Furthermore, when testing the equality, Realm doesn't care the values of the objects. Realm checks only a table and row index (as mentioned "b)"). Because different objects that has the same value are stored in the database is normal.

    An example that two objects are equal is like the following:

    let a = Blurb()
    a.text = "asdf"
    
    let realm = try! Realm()
    try! realm.write {
        realm.add(a)
    }
    
    let b = realm.objects(Blurb.self).first!
    print(a == b) // true
    
    0 讨论(0)
  • 2020-12-03 23:47

    Do you know how comparison protocols works on iOS?

    If you don't, check here http://nshipster.com/swift-comparison-protocols/

    Basically if you do

    let a = NSObject()
    let b = NSObject()
    let c = a
    a == b // false
    a == c // true
    

    You should create a class like this conform to Equatable

    class MyClass: Equatable {
      let myProperty: String
    
      init(s: String) {
        myProperty = s
      }
    }
    
    func ==(lhs: MyClass, rhs: MyClass) -> Bool {
      return lhs.myProperty == rhs.myProperty
    }
    
    let myClass1 = MyClass(s: "Hello")
    let myClass2 = MyClass(s: "Hello")
    myClass1 == myClass2 // true
    myClass1 != myClass2 // false
    myClass1 === myClass2 // false
    myClass1 !== myClass2 // true
    

    I suggest to check .text for testing

    func testRealmEquality() {
        let a = Blurb()
        a.text = "asdf"
        let b = Blurb()
        b.text = "asdf"
        XCTAssertEqual(a.text, b.text)
    }
    
    0 讨论(0)
提交回复
热议问题