Build Status CocoaPods CocoaPods Carthage codecov codebeat badge Join at Telegram Linux Compatible


URLSession 的另一个网络封装器。旨在使其简单、小巧且易于在应用程序的网络层轻松创建测试。

安装

Carthage

要使用 Carthage 将 Frisbee 集成到您的 Xcode 项目中,请在您的 Cartfile 中指定它

github "ronanrodrigo/Frisbee" ~> 0.2.5

运行 `carthage update` 来构建框架,并将构建好的 Frisbee.framework 拖到您的 Xcode 项目中。

CocoaPods

要使用 CocoaPods 将 Frisbee 集成到您的 Xcode 项目中,请在您的 Podfile 中指定它

source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '10.0'
use_frameworks!

target '<Your Target Name>' do
    pod 'Frisbee', '0.2.5'
end

然后,运行以下命令

$ pod install

Swift Package Manager

要将 Frisbee 集成到您的 Swift Package Manager 项目中,请在您的 Package.swift 中设置依赖项

// swift-tools-version:4.0

import PackageDescription

let package = Package(
    name: "<Your Packege Name>",
    dependencies: [
        .package(url: "https://github.com/ronanrodrigo/Frisbee.git", from: "0.2.5")
    ],
    targets: [
        .target(name: "<Your Packege Name>", dependencies: ["Frisbee"])
    ]
)

用法

GET 请求

可解码实体

在 Frisbee 中发出的 RequestResponse 将返回 Result<T> 枚举。其中 T 必须是可解码的实体。在本指南中,将使用如下所示的 Movie 实体。

struct Movie: Decodable {
    let name: String
}

发起请求

您可以将 Frisbee 用法抽象到某个类中,并注入一个符合 Getable 协议的对象。因此,在生产就绪的代码中,您将使用 NetworkGet 对象的实例。

class MoviesController {
    private let getRequest: Getable

    // Expect something that conforms to Getable
    init(getRequest: Getable) {
        self.getRequest = getRequest
    }

    func listMovies() {
        getRequest.get(url: someUrl) { moviesResult: Result<[Movie]> in
            switch moviesResult {
                case let .success(movies): print(movies[0].name)
                case let .fail(error): print(error)
            }
        }
    }
}
// Who will call the MoviesController must inject a NetworkGet instance
MoviesController(getRequest: NetworkGet())

查询参数

使用查询参数非常容易。只需创建一个 Encodable 结构体,并在 get(url:query:onComplete:) 方法中使用它。

struct MovieQuery: Encodable {
    let page: Int
}
let query = MovieQuery(page: 10)
NetworkGet().get(url: url, query: query) { (result: Result<Movie>) in
    // ...
}

POST 请求

与 GET 请求相同,Frisbee 也有一个 Postable 协议。在生产就绪的代码中,您将使用 NetworkPost 的实例。

发起请求

这与 GET 请求的逻辑相同。

class MoviesController {
    private let postRequest: Postable

    // Expect something that conforms to Postable
    init(postRequest: Postable) {
        self.postRequest = postRequest
    }

    func createMovie() {
        postRequest.post(url: someUrl) { moviesResult: Result<[Movie]> in
            switch moviesResult {
                case let .success(movies): print(movies[0].name)
                case let .fail(error): print(error)
            }
        }
    }
}

请求体参数

使用请求体参数非常容易。只需创建一个 Encodable 结构体,并在 post(url:body:onComplete:) 方法中使用它。

struct MovieBody: Encodable {
    let name: String
}
let body = MovieBody(name: "A New Movie")
NetworkPost().post(url: url, body: body) { (result: Result<Movie>) in
    // ...
}

在测试中使用

在测试目标代码中,您可以创建自己的 Getable(或根据需要 Postable)模拟 (mock) 对象。

public class MockGet: Getable {
    var decodableMock: Decodable!

    public func get<Entity: Decodable>(url: URL, completionHandler: @escaping (Result<Entity>) -> Void) {
        get(url: url.absoluteString, completionHandler: completionHandler)
    }

    public func get<Entity: Decodable>(url: String, completionHandler: @escaping (Result<Entity>) -> Void) {
        if let decodableMock = decodableMock as? Entity {
            completionHandler(.success(decodableMock))
        }
    }

}

然后,您将使用 MockGet 而不是 NetworkGetMoviesController 上进行测试

class MoviesControllerTests: XCTestCase {
    func testDidTouchAtListMoviesWhenHasMoviesThenPresentAllMovies() {
        let mockGet = MockGet()
        let movies = [Movie(name: "Star Wars")]
        mockGet.decodableMock = movies
        let controller = MoviesController(getRequest: mockGet)

        controller.didTouchAtListMovies()

        XCTAssertEqual(controller.moviesQuantity, movies.count)
    }
}

Frisbee 的未来特性

Telegram

要协作、解决问题并了解有关 Frisbee 库的最新信息,请加入 Telegram 群组:https://t.me/FrisbeeLib