【问题标题】:How to mock final class and static func for unit test with Swift?如何使用 Swift 模拟最终类和静态函数以进行单元测试?
【发布时间】:2021-10-04 22:16:15
【问题描述】:

我有一个带有static 函数的类。

UserAuthentication.swift

final class UserAuthentication {
    /// Check is logged in
    /// - Returns: boolean true is login, false not login
    @objc public static func isLogin() -> Bool {
        return true
    }
}

我想为checkTermAndCondition 函数编写一个单元测试,在我的HomeInteractor 类中调用它

HomeInteractor.swift

class HomeInteractor: HomeInteractorBusinessLogic {
    var presenter: HomePresenterInterface!
    var worker: HomeWorker = HomeWorker(with: HomeService())
    
    func checkTermAndCondition() {
        if UserAuthentication.isLogin() {
            ///do true case
        } else {
            ///do fasle case
        }
    }
}

有人做过吗? 感谢您提供的任何帮助。

【问题讨论】:

    标签: ios swift unit-testing xctest


    【解决方案1】:

    您不能在 final 类上模拟 static 方法。

    您应该将方法更改为class 并使该类成为非最终类或更好,将UserAuthentication 作为协议注入HomeInteractor 并在您的单元测试中注入模拟类型而不是您的实际生产输入。

    protocol UserAuthenticator {
        /// Check is logged in
        /// - Returns: boolean true is login, false not login
        static func isLogin() -> Bool
    }
    
    final class UserAuthentication: UserAuthenticator {
        @objc public static func isLogin() -> Bool {
            return true
        }
    }
    
    final class UserAuthenticationMock: UserAuthenticator {
        static var shouldLogin: Bool = false
    
        static func isLogin() -> Bool {
            shouldLogin
        }
    }
    
    
    class HomeInteractor: HomeInteractorBusinessLogic {
        var presenter: HomePresenterInterface!
        var worker: HomeWorker = HomeWorker(with: HomeService())
        let userAuthenticator: UserAuthenticator.Type
    
        init(userAuthenticator: UserAuthenticator.Type) {
            self.userAuthenticator = userAuthenticator
        }
    
        func checkTermAndCondition() {
            if userAuthenticator.isLogin() {
    
            } else {
    
            }
        }
    }
    

    为您的产品代码注入UserAuthentication.self,而为测试注入UserAuthenticationMock.self

    let prodHomeInteractor = HomeInteractor(userAuthenticator: UserAuthentication.self)
    let testHomeInteractor = HomeInteractor(userAuthenticator: UserAuthenticationMock.self)
    

    【讨论】:

    • 非常感谢您的回答。我可以再问一个问题 .self 是什么意思吗?它发送最终类的类型或引用?
    • @NawinPoolsawad self 在类型名称的末尾返回元类型(类型的类型)。这是访问类型方法所必需的 (static)。
    • init(userAuthenticator: UserAuthenticator.Type)通知.Type,表示需要传入UserAuthenticator的类型。通常我们将类/结构的实例传递给函数,在这种情况下,我们传递的是 UserAuthenticator 类型。使用类型我们可以在类型上调用静态函数,我们不需要实例,因为我们使用的是静态函数。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-29
    • 1970-01-01
    • 2018-08-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多