使用final快速模拟

Mik*_*keH 6 unit-testing swift

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

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

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

谢谢,迈克。

Sep*_*pui 5

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

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

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
    }
}
Run Code Online (Sandbox Code Playgroud)

然后在测试中:

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
    }
}
Run Code Online (Sandbox Code Playgroud)


Cha*_* A. 4

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

不幸的是,你不能两者兼得。您可以不将其标记为 Final,这样您就可以提供一个模拟子类,也可以将其标记为 Final 以使其静态调度以提高性能。