最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Swift中的HTTP模擬測(cè)試示例詳解

 更新時(shí)間:2023年02月06日 14:49:31   作者:莊周曉夢(mèng)  
這篇文章主要為大家介紹了Swift中的HTTP模擬測(cè)試示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

正文

我們已經(jīng)了解了單個(gè)方法如何為通過(guò)網(wǎng)絡(luò)加載請(qǐng)求提供基礎(chǔ)。

然而,網(wǎng)絡(luò)也是開發(fā)應(yīng)用程序時(shí)最大的失敗點(diǎn)之一,尤其是在單元測(cè)試方面。 當(dāng)我們編寫單元測(cè)試時(shí),我們希望測(cè)試是可重復(fù)的:無(wú)論我們執(zhí)行多少次,我們應(yīng)該總是得到相同的結(jié)果。

如果我們的測(cè)試涉及實(shí)時(shí)網(wǎng)絡(luò)連接,我們無(wú)法保證這一點(diǎn)。 由于我們實(shí)際網(wǎng)絡(luò)請(qǐng)求失敗的所有原因,我們的單元測(cè)試也可能失敗。

因此,我們使用模擬對(duì)象來(lái)模擬網(wǎng)絡(luò)連接,但實(shí)際上提供了一個(gè)一致且可重復(fù)的外觀,我們可以通過(guò)它提供虛假數(shù)據(jù)。

由于我們已將網(wǎng)絡(luò)接口抽象為單個(gè)方法,因此模擬它非常簡(jiǎn)單。

這是一個(gè)始終返回 200 OK 響應(yīng)的 HTTPLoading 實(shí)現(xiàn):

public class MockLoader: HTTPLoading {
    public func load(request: HTTPRequest, completion: @escaping (HTTPResult) -> Void) {
        let urlResponse = HTTPURLResponse(url: request.url!, statusCode: HTTPStatus(rawValue: 200), httpVersion: "1.1", headerFields: nil)!
        let response = HTTPResponse(request: request, response: urlResponse, body: nil)
        completion(.success(response))
    } 
}

我們可以在任何需要 HTTPLoading 值的地方提供 MockLoader 的實(shí)例,發(fā)送給它的任何請(qǐng)求都將導(dǎo)致 200 OK 響應(yīng),盡管主體為 nil。

當(dāng)我們使用模擬網(wǎng)絡(luò)連接編寫單元測(cè)試時(shí),我們并不是在測(cè)試網(wǎng)絡(luò)代碼本身。 通過(guò)模擬網(wǎng)絡(luò)層,我們將網(wǎng)絡(luò)作為變量移除,這意味著網(wǎng)絡(luò)不是被測(cè)試的對(duì)象:?jiǎn)卧獪y(cè)試檢查實(shí)驗(yàn)的變量。

StarWarsAPI 類

我們將使用我們?cè)谏弦黄恼轮袆h除的 StarWarsAPI 類來(lái)說(shuō)明這一原則:

public class StarWarsAPI {
    private let loader: HTTPLoading
    public init(loader: HTTPLoading = URLSession.shared) {
        self.loader = loader
    }
    public func requestPeople(completion: @escaping (...) -> Void) {
        var r = HTTPRequest()
        r.host = "swapi.dev"
        r.path = "/api/people"
        loader.load(request: r) { result in
            // TODO: interpret the result
            completion(...)
        }
    }
}

該類的測(cè)試將驗(yàn)證其行為:我們要確保它在不同情況下的行為正確。 例如,我們要確保 requestPeople() 方法在收到 200 OK 響應(yīng)或 404 Not Found 響應(yīng)或 500 Internal Server Error 時(shí)行為正確。 我們使用 MockLoader 模擬這些場(chǎng)景。 這些測(cè)試將使我們有信心在不破壞現(xiàn)有功能的情況下改進(jìn) StarWarsAPI 的實(shí)現(xiàn)。

MockLoader

為了滿足這些需求,我們的 MockLoader 需要:

保證傳入的請(qǐng)求是我們?cè)跍y(cè)試中期望的請(qǐng)求 為每個(gè)請(qǐng)求提供自定義響應(yīng) 我個(gè)人版本的 MockLoader 大致如下所示:

public class MockLoader: HTTPLoading {
    // typealiases help make method signatures simpler
    public typealias HTTPHandler = (HTTPResult) -> Void
    public typealias MockHandler = (HTTPRequest, HTTPHandler) -> Void
    private var nextHandlers = Array<MockHandler>()
    public override func load(request: HTTPRequest, completion: @escaping HTTPHandler) {
        if nextHandlers.isEmpty == false {
            let next = nextHandlers.removeFirst()
            next(request, completion)
        } else {
            let error = HTTPError(code: .cannotConnect, request: request)
            completion(.failure(error))
        }
    }
    @discardableResult
    public func then(_ handler: @escaping MockHandler) -> Mock {
        nextHandlers.append(handler)
        return self
    }
}

這個(gè) MockLoader 允許我提供如何響應(yīng)連續(xù)請(qǐng)求的個(gè)性化實(shí)現(xiàn)。 例如:

func test_sequentialExecutions() {
    let mock = MockLoader()
    for i in 0 ..< 5 {
        mock.then { request, handler in
            XCTAssert(request.path, "/(i)")
            handler(.success(...))
        }
    }
    for i in 0 ..< 5 {
        var r = HTTPRequest()
        r.path = "/(i)"
        mock.load(r) { result in
            XCTAssertEqual(result.response?.statusCode, .ok)
        }
    }
}

如果我們?cè)跒?StarWarsAPI 類編寫測(cè)試時(shí)使用這個(gè) MockLoader,它可能看起來(lái)像這樣(我省略了 XCTestExpectations,因?yàn)樗鼈兣c本次討論沒有直接關(guān)系):

class StarWarsAPITests: XCTestCase {
    let mock = MockLoader()
    lazy var api: StarWarsAPI = { StarWarsAPI(loader: mock) }()
    func test_200_OK_WithValidBody() {
        mock.then { request, handler in
            XCTAssertEqual(request.path, "/api/people")
            handler(.success(/* 200 OK with some valid JSON */))
        }
        api.requestPeople { ...
            // assert that "StarWarsAPI" correctly decoded the response
        }
    }
    func test_200_OK_WithInvalidBody() {
        mock.then { request, handler in
            XCTAssertEqual(request.path, "/api/people")
            handler(.success(/* 200 OK but some mangled JSON */))
        }
        api.requestPeople { ... 
            // assert that "StarWarsAPI" correctly realized the response was bad JSON
        }
    }
    func test_404() {
        mock.then { request, handler in
            XCTAssertEqual(request.path, "/api/people")
            handler(.success(/* 404 Not Found */))
        }
        api.requestPeople { ... 
            // assert that "StarWarsAPI" correctly produced an error
        }
    }
    func test_DroppedConnection() {
        mock.then { request, handler in
            XCTAssertEqual(request.path, "/api/people")
            handler(.failure(/* HTTPError of some kind */))
        }
        api.requestPeople { ... 
            // assert that "StarWarsAPI" correctly produced an error
        }
    }
    ...
}

當(dāng)我們編寫這樣的測(cè)試時(shí),我們將 StarWarsAPI 視為一個(gè)“黑匣子”:給定特定的輸入條件,它是否總是產(chǎn)生預(yù)期的輸出結(jié)果?

我們的 HTTPLoading 抽象使得交換網(wǎng)絡(luò)堆棧的實(shí)現(xiàn)成為一個(gè)簡(jiǎn)單的改變。 我們所做的只是將 MockLoader 傳遞給初始化程序而不是 URLSession。 這里的關(guān)鍵是意識(shí)到,通過(guò)使我們的 StarWarsAPI 依賴于接口 (HTTPLoading) 而不是具體化 (URLSession),我們極大地增強(qiáng)了它的實(shí)用性并使其更易于單獨(dú)使用(和測(cè)試)。

這種對(duì)特定實(shí)現(xiàn)的行為定義的依賴將在我們實(shí)現(xiàn)框架的其余部分時(shí)很好地為我們服務(wù)。 在下一篇文章中,我們會(huì)將 HTTPLoading 更改為一個(gè)類并添加一個(gè)屬性,該屬性將為我們可以想象的幾乎所有可能的網(wǎng)絡(luò)行為提供基礎(chǔ)。

以上就是Swift中的HTTP模擬測(cè)試示例詳解的詳細(xì)內(nèi)容,更多關(guān)于Swift HTTP模擬測(cè)試的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Swift自動(dòng)調(diào)整視圖布局AutoLayout和AutoresizingMask功能詳解

    Swift自動(dòng)調(diào)整視圖布局AutoLayout和AutoresizingMask功能詳解

    這篇文章主要為大家介紹了Swift自動(dòng)調(diào)整視圖布局AutoLayout和AutoresizingMask功能及使用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-06-06
  • RxSwift學(xué)習(xí)教程之基礎(chǔ)篇

    RxSwift學(xué)習(xí)教程之基礎(chǔ)篇

    RxSwift是Swift函數(shù)響應(yīng)式編程的一個(gè)開源庫(kù),由Github的ReactiveX組織開發(fā),維護(hù)。下面這篇文章主要給大家介紹了關(guān)于RxSwift學(xué)習(xí)之基礎(chǔ)篇的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面來(lái)一起看看吧。
    2017-09-09
  • Swift中defer關(guān)鍵字推遲執(zhí)行示例詳解

    Swift中defer關(guān)鍵字推遲執(zhí)行示例詳解

    這篇文章主要給大家介紹了關(guān)于Swift中defer關(guān)鍵字推遲執(zhí)行的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。
    2018-03-03
  • 在Mac OS的終端中運(yùn)行Swift應(yīng)用的方法

    在Mac OS的終端中運(yùn)行Swift應(yīng)用的方法

    這篇文章主要介紹了在Mac OS的終端中運(yùn)行Swift應(yīng)用的方法,依靠Xcode的REPL功能來(lái)實(shí)現(xiàn),需要的朋友可以參考下
    2015-07-07
  • Swift教程之基本運(yùn)算符詳解

    Swift教程之基本運(yùn)算符詳解

    這篇文章主要介紹了Swift教程之基本運(yùn)算符詳解,本文講解了賦值運(yùn)算符、數(shù)學(xué)運(yùn)算符、取余運(yùn)算符、浮點(diǎn)余數(shù)計(jì)算、自增和自減運(yùn)算符等,需要的朋友可以參考下
    2015-01-01
  • Swift讓輸入框跟隨鍵盤彈起避免輸入輸入法擋住輸入框問(wèn)題

    Swift讓輸入框跟隨鍵盤彈起避免輸入輸入法擋住輸入框問(wèn)題

    這篇文章主要介紹了Swift讓輸入框跟隨鍵盤彈起避免輸入輸入法擋住輸入框問(wèn)題的完美解決方案,本文分步驟給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2016-11-11
  • SwiftUI 登錄界面布局實(shí)現(xiàn)示例詳解

    SwiftUI 登錄界面布局實(shí)現(xiàn)示例詳解

    這篇文章主要為大家介紹了SwiftUI 登錄界面布局實(shí)現(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-09-09
  • swiftui開發(fā)之padding默認(rèn)值設(shè)置詳解

    swiftui開發(fā)之padding默認(rèn)值設(shè)置詳解

    這篇文章主要為大家介紹了swiftui開發(fā)之padding默認(rèn)值設(shè)置詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-09-09
  • SwiftUI學(xué)習(xí)之state和Binding的區(qū)別淺析

    SwiftUI學(xué)習(xí)之state和Binding的區(qū)別淺析

    這篇文章主要給大家介紹了關(guān)于SwiftUI學(xué)習(xí)之state和Binding區(qū)別的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-03-03
  • Swift Extension擴(kuò)展得使用詳細(xì)介紹

    Swift Extension擴(kuò)展得使用詳細(xì)介紹

    在swift中,extension與Objective-C的category有點(diǎn)類似,但是extension比起category來(lái)說(shuō)更加強(qiáng)大和靈活,它不僅可以擴(kuò)展某種類型或結(jié)構(gòu)體的方法,同時(shí)它還可以與protocol等結(jié)合使用,編寫出更加靈活和強(qiáng)大的代碼
    2022-09-09

最新評(píng)論

孟连| 涡阳县| 万安县| 阳高县| 平南县| 天峻县| 福海县| 定州市| 子洲县| 荣成市| 垦利县| 沈丘县| 沈丘县| 定州市| 新化县| 新化县| 静宁县| 新源县| 林周县| 鄢陵县| 育儿| 团风县| 苏尼特右旗| 和田县| 和田县| 昌邑市| 岢岚县| 舒城县| 安乡县| 游戏| 寿宁县| 陆丰市| 安岳县| 土默特右旗| 砚山县| 井陉县| 乌拉特前旗| 临汾市| 伊金霍洛旗| 辉县市| 明水县|