无法使用协议类型将符合协议的值设置为属性

时间:2018-04-05 15:14:53

标签: ios swift unit-testing

我试图为我的单元测试创​​建一个假身份验证器,可以手动将用户设置为登录或注销,并绕过我的代码实际使用的API,我需要一个真正的accessToken来记录用户在。

我已将我的应用使用的身份验证API包装到以下类中:

API Wrapper

import OIDC

protocol Authenticator {
    func getValidAccessToken(completionHandler: @escaping (Error?, String?) -> Void)
}

struct OIDCAuthenticator: Authenticator {

    func getValidAccessToken(completionHandler: @escaping (Error?, String?) -> Void) {
        //API call
        OIDCHelper.getValidAccessToken { (error, accessToken) in
            DispatchQueue.main.async {
                completionHandler( error, accessToken)
            }
        }
    }
}

然后我使用相同的协议创建一个虚假身份验证器以进行测试

假/测试身份验证器

import OIDC
import Foundation

///Mocks the user being logged in our logged out for Testing purposes
struct FakeAuthenticator: Authenticator {
    let error: OIDCError?
    let accessToken: String?

    func getValidAccessToken(completionHandler: @escaping (Error?, String?) -> Void) {
        completionHandler(error, accessToken)
    }

    init(loggedIn: Bool) {
        if loggedIn {
            error = .tokenNotFoundInKeychainData
            accessToken = nil
        } else {
            error = nil
            accessToken = "abcdefg"
        }
    }
}

OIDCAuthenticator子类中设置身份验证器时,ViewController API包装器设置正常。

TableViewController实施

import UIKit
import OIDC

class SettingsPageTableViewController: UITableViewController{

    // MARK: - Outlets and variables

    var authenticator: Authenticator!
    private var isUserLoggedIn = false

    // MARK: - LifeCycle

    override func viewDidLoad() {
        super.viewDidLoad()
        authenticator = OIDCAuthenticator()
    }

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        authenticator.getValidAccessToken { [weak self] (error, _) in
            self?.isUserLoggedIn = (error == nil)
            self?.setLogginStatus()
        }
    }
}

但是当我尝试在我的单元测试中对FakeAuthenticator做同样的事情时,我收到以下错误: enter image description here

SettingsViewController测试类

import XCTest
import UIKit
@testable import MyProject

class SettingsViewControllerTests: XCTestCase {

    var viewController: SettingsPageTableViewController!

    override func setUp() {
        super.setUp()
        configureViewControllerForTesting()
    }

    private func configureViewControllerForTesting() {
        let storyboard = UIStoryboard(name: "SettingsPage", bundle: nil)
        let navigationController = storyboard.instantiateInitialViewController() as! UINavigationController
        viewController = navigationController.topViewController as! SettingsPageTableViewController
        _ = viewController.view
    }

    func testSignInButtonIsAvailableWhenUnauthenticated() {
        viewController.authenticator = FakeAuthenticator(loggedIn: false)
    }
}

当我用FakeAuthenticator换出OIDCAuthenticator时,会发生同样的事情。我还尝试将FakeAuthenticator转换为Authenticator,但这只会将错误更改为Cannot assign value of type 'Authenticator' to type 'Authenticator!'.

为什么我会收到此错误,解决此问题的最佳方法是什么?

1 个答案:

答案 0 :(得分:1)

您需要从测试目标中删除文件,因为您已经使用@testable导入了整个项目。