【问题标题】:Testing for equality in Realm在 Realm 中测试相等性
【发布时间】:2016-08-10 09:00:23
【问题描述】:

我正在尝试在单元测试中测试 Realm 对象之间的相等性。但是,我无法让对象返回 true 以保证它们的相等性。

根据Realm docs here,我应该可以做到:

let expectedUser = User()
expectedUser.email = "help@realm.io"
XCTAssertEqual(testRealm.objects(User.self).first!,
               expectedUser,
               "User was not properly updated from server.")

但是,我使用以下代码得到以下测试失败:

领域模型

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

测试

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

XCTAssertEqual 失败:(“可选(Blurb {
文本 = asdf;
})") 不等于 ("Optional(Blurb {
文本 = asdf;
})")

【问题讨论】:

    标签: ios swift xcode testing realm


    【解决方案1】:

    来自 Realm 的 Katsumi。 Realm 对象的Equatable 实现如下:

    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();
    }
    

    总而言之,a) 如果两个对象都是非托管的,它的工作方式与普通对象的Equatable 相同。 b) 如果两个对象都是托管的,如果它们是相同的表(类)和索引,它们是相等的。 c) 如果一个是托管的,另一个是非托管的,那么它们就不相等。

    “托管”表示对象已存储在 Realm 中。

    所以你的代码中的ab 是不相等的。因为ab 是非托管的(没有存储在Realm 中)并且它们是不同的对象。

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

    此外,在测试相等性时,Realm 并不关心对象的值。 Realm 只检查表和行索引(如“b)”所述)。因为不同的对象存在相同的值在数据库中是正常的。

    两个对象相等的例子如下:

    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
    

    【讨论】:

    • 感谢您的解释。但是,在领域文档代码示例中,expectedUser 不是一个仅具有相同电子邮件属性值的非托管对象吗?为什么该测试会通过?
    • @solidcell 很抱歉造成混乱。我认为该文件不正确或为简单起见省略了某些内容。我会尽快修复文档的问题,谢谢指出!
    • 这种行为改变了吗?看起来至少从 Realm 3.7.4 开始,Equatable 仅适用于具有主键的对象;当我在没有主键的类上尝试与上述类似的创建/添加/检索循环时,我得到 isSameObject(as:) 返回 true,但 isEqual() 返回 false。
    【解决方案2】:

    您知道比较协议在 iOS 上的工作原理吗?

    如果没有,请查看此处 http://nshipster.com/swift-comparison-protocols/

    基本上如果你这样做

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

    你应该创建一个这样的类符合 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
    

    我建议检查 .text 进行测试

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

    【讨论】:

    • 是的,我知道Equatable 是如何工作的,但是我不确定Realm 是如何实现它的,也不知道为什么他们的文档显示它显然能够用于测试具有可比性的对象(但是不是同一个确切的对象)。如果可能的话,我宁愿不必为数组中的每个对象测试每个属性。这往往会失控。
    • 最后的建议。您是否检查过有关此的 Realm 文档? realm.io/docs/swift/latest/#testing
    • 是的,看看我的问题的开头,你会看到我已经链接到文档并粘贴了相关的 sn-p。
    • 是的。对不起这个问题。我用 Realm 和 TDD 检查了我的项目,但我从不比较整个对象。
    猜你喜欢
    • 2021-09-24
    • 1970-01-01
    • 2011-11-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-02
    • 1970-01-01
    相关资源
    最近更新 更多