两个类,回调和单元测试

时间:2015-08-07 19:34:37

标签: ios swift asynchronous

我有一个静态方法的类:这个类包装了对Twitter API的调用

在第二节课中,我有一些商业逻辑。

由于包装类中某些方法的异步行为,我很难设计通信。这就是我所做的:

APIManager.swift

public class APIManager {
    class func getPermission(callback : () -> Void) {

        let accountStore = ACAccountStore()
        let accountType = 
        ACAccountStore().accountTypeWithAccountTypeIdentifier(ACAccountTypeIdentifierTwitter)

        let callbackRequestAccess = { (granted: Bool, error: NSError!) -> Void in
            ...
            if(granted) {
                callback()
            }

        }

        accountStore.requestAccessToAccountsWithType(setAccountType, 
                     options: nil, completion: callbackRequestAccess)

    }
}

Welcome.swift

public class Welcome {

    public func checkPermission() {
        APIManager.getPermission(getTweet)
    } 
    public func getTweet() {
        ...
    }        
}

我不确定这个设计是否合适。 我不想在这些类之间建立强大的联系,这就是我使用回调的原因。

这是经典设计吗? 而且,我觉得这种行为不容易测试吗?

2 个答案:

答案 0 :(得分:7)

通过不使用类方法,您将大大提高可测试性。创建TwitterConnection协议。创建符合它的SystemTwitterConnection并通过ACAccountStore管理事物。创建一个TestTwitterConnection,返回您可以配置用于测试的预设响应。您甚至可以创建KeychainTwitterConnection来手动管理Twitter登录而不使用ACAccountStore,或者如果Apple推出另一种存储这些帐户的方法,则可以创建其他实现。

创建时将适当的连接传递给Welcome

如果TwitterConnection协议变大,您应该强烈考虑将其拆分为较小的协议,例如处理较少事情的TwitterAuthenticatorTweetFetcher(即使单个类型实际实现所有这些协议)。通过允许您的测试类型仅实现几个函数而不是几十个函数,这可以使测试变得更加容易。

闭包的使用可能很好,但你应该更贴近Cocoa命名约定。您所谓的callback传统上称为completion。我还会关注Cocoa在如何命名方法方面的领先优势。它不是getPermission(),而是requestAccessWithCompletionHandler()。这将有助于调用者理解它与requestAccessToAccountsWithType(options:completion:)具有非常相似的行为。不要为调用者构建新的词汇表。

答案 1 :(得分:1)

https://en.wikipedia.org/wiki/Observer_pattern

它将帮助您解耦事件发布者(Observable)和消费者(Observer) 你也可以有一个特殊的Observable实现
它不会连接到任何地方,而是通过静态内容通知观察者 所以你直接调用notifyObservers方法来测试Observers的行为。