【问题标题】:swift mocking using final使用 final 快速模拟
【发布时间】:2015-11-02 21:55:00
【问题描述】:

为了测试 swift 对象,根据我的阅读,我们对它们进行子类化并模拟我们想要返回测试值的方法。然后我观看了一个关于 Swift 性能的 WWDC 视频,演示者建议将类标记为 final 以帮助编译器决定如何调用方法,并且从我看到的示例中添加 final 会有所帮助。

我遇到的问题我们如何将类标记为最终但仍启用子类模拟?有没有人真正遇到过这个问题,或者我应该从我的声明中删除 final 关键字?

任何建议都会很棒,或者如果没有,请告诉我我做得不对。

谢谢, 迈克。

【问题讨论】:

  • final 是 final ... 没有从 final 类继承。

标签: swift unit-testing


【解决方案1】:

我知道这个帖子有点老了,但我想我还是会发表评论。您的另一个选择是面向协议。在协议中定义您的public 接口到您的最终类,并使final class 实现该协议。然后你所要做的就是模拟协议并且你的课程保持最终状态。这为您提供了静态调度和模拟。我不确定这是否是 best 选项本身,但它是我在框架构建中一直使用的选项,以便我们可以测试我们的框架代码,同时为消费应用。

internal protocol MockableProtocol {
    func deleteItem(_ itemId: String) -> Bool
    func fetchAllItems() -> [CustomObject]
    func fetchItem(for id: String) -> CustomObject?
}

internal final class MyFinalClass: MockableProtocol {
    func deleteItem(_ itemId: String) -> Bool {
        // Your code here
    }

    func fetchAllItems() -> [CustomObject] {
        // Your code here
    }

    func fetchItem(for id: String) -> CustomObject? {
        // Your code here
    }
}

然后在测试中:

class TestMockClass: MockableProtocol {
    func deleteItem(_ itemId: String) -> Bool {
        // Your code here
    }

    func fetchAllItems() -> [CustomObject] {
        // Your code here
    }

    func fetchItem(for id: String) -> CustomObject? {
        // Your code here
    }
}

【讨论】:

    【解决方案2】:

    当您将某些内容标记为final 时,编译器使用静态分派而不是动态分派。这具有非常显着的性能优势。这也与能够模拟某些东西直接相反,因为静态调度的全部意义在于它不必弄清楚要调用的方法的版本。

    不幸的是,你不能同时拥有它。您可以不将其标记为 final,因此您可以提供一个模拟的子类,或者您可以将其标记为 final 以使其静态调度以提高性能。

    【讨论】:

    • 那么如何对依赖于第三方库的最终类的东西进行单元测试呢?通常我只是继承并换掉它,但这听起来不太可能。
    • 您最好的选择可能是围绕最终的第三方类创建一个简单的包装器并创建一个模拟。不理想,但您没有太多选择。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-06
    • 1970-01-01
    • 2012-10-19
    • 1970-01-01
    相关资源
    最近更新 更多