首页 > 解决方案 > 测试 AuthenticationServices 的接口适配器类

问题描述

我有一个名为 AppleSignInAdapter 的接口适配器类,它将使用 Apple 的 AuthenticationServices。这是课程:

import AuthenticationServices
import RxSwift

enum AppleSignInError: Error {
    case credentialsIncomplete
}

struct AppleSignInParam {
    let authCode: String
    let idToken: String
    let email: String
    
    @available(iOS 13.0, *)
    init?(authorization: ASAuthorization) {
        guard let credential = authorization.credential as? ASAuthorizationAppleIDCredential,
              let authCodeData = credential.authorizationCode,
              let authCode = String(data: authCodeData, encoding: .utf8),
              let idTokenData = credential.identityToken,
              let idToken = String(data: idTokenData, encoding: .utf8),
              let email = credential.email
        else { return nil }
        
        self.authCode = authCode
        self.idToken = idToken
        self.email = email
    }
}

final class AppleSignInAdapter {
    
    func handleSignIn() -> Observable<AppleSignInParam> {
        if #available(iOS 13.0, *) {
            let authController = createAuthController()
            
            // didCompleteWithAuthorization and didCompleteWithError are functions from
            // ASAuthorizationControllerDelegate that are implemented using RxCocoa's DelegateProxy

            let authSuccessEvent = authController.rx
                .didCompleteWithAuthorization
                .compactMap { authorization -> AppleSignInParam? in
                    guard let param = AppleSignInParam(authorization: authorization) else {
                        throw AppleSignInError.credentialsIncomplete
                    }
                    
                    return param
                }
            
            let authErrorEvent = authController.rx
                .didCompleteWithError
                .flatMapLatest { error -> Observable<AppleSignInParam> in
                    return .error(error)
                }
            
            let appleSignInEvent = authSuccessEvent.amb(authErrorEvent).take(1)
            
            return appleSignInEvent
        } else {
            return .empty()
        }
    }
}

@available(iOS 13.0, *)
private func createAuthController() -> ASAuthorizationController {
    let appleIdProvider = ASAuthorizationAppleIDProvider()
    let request = appleIdProvider.createRequest()
    request.requestedScopes = [.email]
    
    let authController = ASAuthorizationController(authorizationRequests: [request])
    authController.performRequests()
    return authController
}

我在想如何为这个类做单元和集成测试。我被困在测试中,因为我无法真正模拟“使用 Apple 登录”的过程并手动触发委托(例如,如何测试成功、错误或AppleSignInError.credentialsIncomplete错误)。还有一个事实是整个过程都是由 AuthenticationServices 处理的,所以我不能模拟输入本身。关于如何测试这个的任何想法?还是我应该只使用 UITest 来测试功能?

谢谢。

标签: iosswiftunit-testingintegration-testingapple-sign-in

解决方案


推荐阅读