我正在尝试为我的单元测试创建一个伪造的身份验证器,它可以手动将用户设置为已登录或已注销,并绕过我的代码实际使用的 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
做同样的事情时,我收到以下错误:
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/