Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Testing for equality in Realm

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.

According to the Realm docs here, I should be able to do that:

let expectedUser = User()
expectedUser.email = "[email protected]"
XCTAssertEqual(testRealm.objects(User.self).first!,
               expectedUser,
               "User was not properly updated from server.")

However, I get the following test failure with the following code:

Realm Model

class Blurb: Object {
    dynamic var text = ""
}

Test

func testRealmEquality() {
    let a = Blurb()
    a.text = "asdf"
    let b = Blurb()
    b.text = "asdf"
    XCTAssertEqual(a, b)
}

XCTAssertEqual failed: ("Optional(Blurb {
text = asdf;
})") is not equal to ("Optional(Blurb {
text = asdf;
})")

like image 271
solidcell Avatar asked Aug 10 '16 09:08

solidcell


1 Answers

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
like image 195
kishikawa katsumi Avatar answered Sep 27 '22 23:09

kishikawa katsumi