这取决于您要测试的login use case 的哪个“部分”,为您的项目提供一个具体的HTTPClient? (URLSession、Alamofire 等),或者这个服务的实现,但我会给你一些建议。
尝试使用 DI(依赖注入)来准备您的声明(类、结构、函数...),以便使用协议或继承进行测试(在大多数情况下,协议是最佳选择)。然后,评估所有可能的响应情况。我已经为登录服务用例演示做了一个简单的实现。
//
// Created by Wilmer Barrios.
//
import XCTest
// Business Logic
struct LoginResponse {
let succeed: Bool
}
protocol LoginService {
func login(username: String, password: String, completion: @escaping (Result<LoginResponse, Error>) -> Void)
}
// Implementation
class LoginController {
// Presented values
var presentedSucceedMessage: String?
var presentedErrorMessage: String?
// Elements (Could be textfields)
var username: String = ""
var password: String = ""
private let service: LoginService
init(service: LoginService) {
self.service = service
}
func login() {
service.login(username: username, password: password, completion: { [weak self] result in
if let response = try? result.get(), response.succeed {
self?.presentedSucceedMessage = "Login succeed!"
} else {
self?.presentedErrorMessage = "Login error!"
}
})
}
}
class LoginControllerTests: XCTestCase {
func test_init_doesNotLogin() {
let (_, service) = makeSUT()
XCTAssertEqual(service.callCount, 0)
}
func test_login_doesLoadService() {
let (sut, service) = makeSUT()
sut.login()
XCTAssertEqual(service.callCount, 1)
}
func test_loginSucceed_presentsSucceedMessage() {
let (sut, service) = makeSUT()
sut.login()
service.complete(result: .success(makeLoginResponse()))
XCTAssertEqual(sut.presentedSucceedMessage, "Login succeed!")
XCTAssertNil(sut.presentedErrorMessage)
}
func test_loginError_presentsErrorMessage() {
let (sut, service) = makeSUT()
sut.login()
service.complete(result: .success(makeLoginResponse(succeed: false)))
XCTAssertEqual(sut.presentedErrorMessage, "Login error!")
XCTAssertNil(sut.presentedSucceedMessage)
}
func test_loginFailed_presentsErrorMessage() {
let (sut, service) = makeSUT()
sut.login()
service.complete(result: .failure(makeError()))
XCTAssertEqual(sut.presentedErrorMessage, "Login error!")
XCTAssertNil(sut.presentedSucceedMessage)
}
// MARK: Helpers
private func makeError() -> Error {
return NSError(domain: "anyError", code: 1)
}
private func makeLoginResponse(succeed: Bool = true) -> LoginResponse {
return LoginResponse(succeed: succeed)
}
private func makeSUT() -> (sut: LoginController, service: LoginServiceMock) {
let service = LoginServiceMock()
let sut = LoginController(service: service)
return (sut, service)
}
private class LoginServiceMock: LoginService {
var callCount: Int = 0
private var completion: ((Result<LoginResponse, Error>) -> Void)?
func login(username: String, password: String, completion: @escaping (Result<LoginResponse, Error>) -> Void) {
callCount += 1
self.completion = completion
}
// Helpers
func complete(result: Result<LoginResponse, Error>) {
completion?(result)
}
}
}
在这个例子中,您可以请求任何登录服务,可以是您自己的 API、Firebase、任何 SDK,甚至是本地的!您只需使服务客户端符合 LoginService 协议。即AlamoFireLoginClient、URLSessionLoginClient、FirebaseLoginClient 等。
希望我能帮上忙!