将mock类注入单元测试方法的方法中

时间:2015-01-23 18:04:07

标签: ios swift

我正在尝试对依赖于另一个类的方法进行单元测试。该方法在该类上调用一个类方法,基本上是这样的:

func myMethod() {

     //do stuff
     TheirClass.someClassMethod()

}

使用依赖注入技术,我希望能够用模拟替换“TheyClass”,但我无法弄清楚如何做到这一点。有没有办法传入模拟(不是实例)?

编辑:感谢您的回复。也许我应该提供更多细节。我试图模拟的类方法是在一个开源库中。

以下是我的方法。我试图测试它,同时嘲笑对NXOAuth2Request.performMethod的调用。此类方法发出网络调用以从后端获取经过身份验证的用户的信息。在闭包中,我将此信息保存到开源库提供的全局帐户存储中,并发布成功或失败的通知。

func getUserProfileAndVerifyUserIsAuthenticated() {

    //this notification is fired when the refresh token has expired, and as a result, a new access token cannot be obtained
    NSNotificationCenter.defaultCenter().addObserver(self, selector: "didFailToGetAccessTokenNotification", name: NXOAuth2AccountDidFailToGetAccessTokenNotification, object: nil)

    let accounts = self.accountStore.accountsWithAccountType(UserAuthenticationScheme.sharedInstance.accountType) as Array<NXOAuth2Account>
    if accounts.count > 0 {
        let account = accounts[0]

        let userInfoURL = UserAuthenticationScheme.sharedInstance.userInfoURL

        println("getUserProfileAndVerifyUserIsAuthenticated: calling to see if user token is still valid")
        NXOAuth2Request.performMethod("GET", onResource: userInfoURL, usingParameters: nil, withAccount: account, sendProgressHandler: nil, responseHandler: { (response, responseData, error) -> Void in

            if error != nil {
                println("User Info Error: %@", error.localizedDescription);
                NSNotificationCenter.defaultCenter().postNotificationName("UserCouldNotBeAuthenticated", object: self)
            }
            else if let data = responseData {
                var errorPointer: NSError?
                let userInfo = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: &errorPointer) as NSDictionary

                println("Retrieved user info")
                account.userData = userInfo

                NSNotificationCenter.defaultCenter().postNotificationName("UserAuthenticated", object: self)
            }
            else {
                println("Unknown error retrieving user info")
                NSNotificationCenter.defaultCenter().postNotificationName("UserCouldNotBeAuthenticated", object: self)
            }
        })
    }
}

1 个答案:

答案 0 :(得分:6)

在Swift中,通过传递函数可以做得更好。有很多方法可以解决这个问题,但这里有一个:

func myMethod(completion: () -> Void = TheirClass.someClassMethod) {
    //do stuff
    completion()
}

现在您可以传递完成处理程序,而现有代码将继续使用默认方法。请注意如何引用函数本身(TheirClass.someClassMethod)。你不必把它包起来。

您可能会发现让调用者始终通过此操作而不是将其设置为默认值会更好。这会使这个类不那么绑定到TheirClass,但无论哪种方式都没问题。

最好将这种松散耦合,可测试性设计集成到代码本身,而不是想出一些聪明的方法来模拟事物。事实上,您应该问自己myMethod()是否应该真正调用someClassMethod()。也许这些东西应该分开以使它们更容易测试,然后将它们连接在一起。例如,也许myMethod应该返回一些你可以传递给someClassMethod()的东西,这样就没有你需要担心的状态了。