ios - 无法将符合协议(protocol)的值设置为具有协议(protocol)类型的属性

标签 ios swift unit-testing

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

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

API 包装器

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)
            }
        }
    }
}

然后我使用相同的协议(protocol)创建一个 Fake Authenticator 用于测试目的

伪造/测试验证器

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"
        }
    }
}

ViewController 子类中设置身份验证器时,设置 OIDCAuthenticator 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!'。

为什么会出现此错误?解决此问题的最佳方法是什么?

最佳答案

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

关于ios - 无法将符合协议(protocol)的值设置为具有协议(protocol)类型的属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49675915/

相关文章:

ios - GrowingTextView 或 UItableview 单元格内的可扩展 TextView

ios - 执行 iOS 应用程序的硬关闭并在带有自动化的模拟器中以保存的状态重新打开

ios - UILabel 在动态创建的 UIView 上不可见

arrays - 单元测试不工作 - Ruby 使用测试单元

ios - 如何从 JSON 加载特定数据并显示 UICollectionView?

iphone - 位置管理器是在调度队列上创建的

ios - 在我的选项卡栏 View 中,我的 TableView 在启动时无法加载数据,但是当我点击离开并点击返回时数据会出现

ios - 如何在 iOS 中使用 Swift 格式化字符串?

python - 如何在 Python 单元测试中模拟 __version__

angularjs - 控制如何处理 $httpBackend.when() 中的每个捕获