Menguji presenter menggunakan PromiseKit

Pola MVP dalam pengembangan aplikasi seluler adalah cara yang cukup sederhana untuk melepas ViewController dan menghilangkan beberapa logika dalam presenter. Presenter mulai mendapatkan logika yang mudah untuk diuji.


Biarkan ada layar MelodyListViewController menampilkan daftar melodi. Dia memiliki presenter MelodyListPresenter yang memberi tahu ViewController apa yang harus ditampilkan. Presenter akan mengambil data dari layanan MelodyService . MelodyService adalah pembungkus atas basis data dan klien api yang mengunduh melodi. Jika jaringan tersedia, layanan mengambil data dari api, jika tidak dari database. Jenis kesalahan pemuatan disajikan di enum ServiceRequestError .


 protocol MelodyListViewController: class { func showMelodies(melodies: [Melody]) func showLoadError(error: ServiceRequestError) } protocol MelodyListPresenter { var view: MelodyListViewController? { get } var melodyService: MelodyService { get } func fetchMelodies() -> Promise<Void> } extension MelodyListPresenter { func fetchMelodies() -> Promise<Void> { return melodyService.getMelodies().done { melodies in self.view?.showMelodies(melodies: melodies) }.catch { error in self.view?.showLoadError(error: error) } } } protocol MelodyService { func getMelodies() -> Promise<[Melody]> } public enum ServiceRequestError: Error { case unknownError case noNetwork case noData } 

Setelah membangun struktur layar seperti itu, Anda dapat melakukan pengujian. Yakni, menguji penerimaan data oleh presenter. Presenter memiliki ketergantungan MelodyService , jadi Anda perlu mengejek protokol ini. Mari kita sepakat bahwa Melody memiliki metode mocks statis yang mengembalikan daftar nada acak.


 class MelodyServiceMock: MelodyService, ServiceRequestMock { var emulatedResult: ServiceRequestResult = .error(.unknownError) func getMelodies() -> Promise<[Melody]> { let melodies = Melody.mocks() return mock(result: emulatedResult, model: melodies) } } enum ServiceRequestResult { case success case error(ServiceRequestError) } 

Kami juga membasahi ViewController.


 class MelodyListViewControllerMock: MelodyListViewController { var shownMelodies: [Melody]? var shownError: ServiceRequestError? func showMelodies(melodies: [Melody]) { shownMelodies = melodies } func showLoadError(error: ServiceRequestError) { shownError = error } } 

ServiceRequestMock adalah protokol yang memiliki func mock<T>(result: ServiceRequestResult, model: T) -> Promise<T> metode tunggal func mock<T>(result: ServiceRequestResult, model: T) -> Promise<T> , yang mengembalikan Janji. Dalam Janji ini, lagu atau kesalahan boot dilindungi - apa yang ditransmisikan sebagai hasil simulasi.


 protocol ServiceRequestMock { func mock<T>(result: ServiceRequestResult, model: T) -> Promise<T> } extension ServiceRequestMock { func mock<T>(result: ServiceRequestResult, model: T) -> Promise<T> { return Promise { seal in switch result { case .success: return seal.fulfill(model) case .error(let requestError): return seal.reject(requestError) } } } } 

Jadi, kami menyediakan semua yang diperlukan untuk menguji presenter.


 import XCTest import PromiseKit class MelodyListPresenterTests: XCTestCase { let view = MelodyListViewControllerMock() let melodyService = MelodyServiceMock() var presenter: MelodyListPresenterImp! override func setUp() { super.setUp() presenter = MelodyListPresenterImp( melodyService: melodyService, view: view) view.presenter = presenter } func test_getMelodies_success() { // given let melodiesMock = Melody.mocks() melodyService.emulatedResult = .success // when let fetchMelodies = presenter.fetchMelodies() // then fetchMelodies.done { melodies in XCTAssertNotNil(self.view.shownMelodies) XCTAssert(self.view.shownMelodies == melodiesMock) }.catch { _ in XCTFail("Failed melodies upload") } } func test_getMelodies_fail() { // given melodyService.emulatedResult = .error(.noNetwork) // when let fetchMelodies = presenter.fetchMelodies() // then fetchMelodies.done { melodies in XCTFail("Mistakenly uploaded melodies") }.catch { _ in XCTAssertNotNil(self.view.shownError) XCTAssert(self.view.shownError is ServiceRequestError) XCTAssert(self.view.shownError as! ServiceRequestError == .noNetwork) } } } 

Hasilnya, kami mendapat alat yang nyaman untuk menulis tes.

Source: https://habr.com/ru/post/id425069/


All Articles