测试userDefaults和私有功能

时间:2018-11-28 08:00:16

标签: ios swift unit-testing nsuserdefaults

我正在使用Coordinator模式来处理ViewController。

在我的appCoordinator中,我通过用户登录状态设置了rootViewController

protocol Coordinatorbale {
    func coordinate()
}


class AppCoordinator: Coordinatorbale {
    init(){ .... }

    func coordinate() {
       let logedIn = UserDefaults.standard.bool(forKey: "user_logged_in")

        if logedIn {
            window.rootViewController = V1
        else {
            window.rootViewController = V2
        }
    }

}

我该如何测试?

如果我从coordinate函数中删除了逻辑。 新的乐趣将是私人的,然后我仍然无法测试状态。

private func setRootByUserState(logedIn: Bool) {
    if logedIn {
            window.rootViewController = V1
        else {
            window.rootViewController = V2
        }
}

所以我坚持使用private方法或UserDefaults

如何对这种行为进行单元测试?

1 个答案:

答案 0 :(得分:0)

您可以将UserDefaults包装在协议后面。

protocol PreferenceAware {
    var isLoggedIn: Bool { get set }
}

然后让另一个类符合此protocol

struct UserDefaultsPreferences: PreferenceAware {
    private let userLoggedInKey = "user_logged_in"
    get {
        return UserDefaults.standard.bool(forKey: userLoggedInKey)
    }

    set {
        UserDefaults.standard.set(newValue, forKey: userLoggedInKey)
    }
}

您的AppDelegate的变量类型为PreferenceAware,如下所示:

var prefenceContainer: PreferenceAware = UserDefaultsPreferences()

然后像这样在方法中使用它

func coordinate() {
   let loggedIn = preferenceContainer.isLoggedIn

    if loggedIn {
        window.rootViewController = V1
    else {
        window.rootViewController = V2
    }
}

现在,为了进行测试,您可以创建一个符合PreferenceAware的测试对象,在preferenceContainer中更新AppDelegate,并根据需要对其进行控制。

struct MockPreferenceAware: PreferenceAware {
    var isLoggedIn: Bool
}

允许您在测试中执行以下操作:

func testLoggedIn() {
    let mock = MockPreferenceAware(isLoggedIn: true)
    appDelegate.preferenceContainer = mock

    //now you are sure of the path that your code will follow in the coordinate method
}

您还可以在用户未登录时测试流程:

func testNotLoggedIn() {
    let mock = MockPreferenceAware(isLoggedIn: false)
    appDelegate.preferenceContainer = mock

    //now you are sure of the path that your code will follow in the coordinate method
}

请注意,我目前不在编译器附近(可怕的想法是:)),所以我没有测试上面的语法错误,但希望您能理解,并希望这对您有用。