Skip to content

Instantly share code, notes, and snippets.

@GeekTree0101
Created May 27, 2019 02:00
Show Gist options
  • Save GeekTree0101/f5f49478e1c35e1c958d0b30d1453b4e to your computer and use it in GitHub Desktop.
Save GeekTree0101/f5f49478e1c35e1c958d0b30d1453b4e to your computer and use it in GitHub Desktop.
RxVIP2.swift
protocol InteractorInputLogics {
var request: PublishRelay<Void> { get }
}
protocol InteractorOutputLogics {
var response: Observable<String> { get }
}
class Interactor: InteractorInputLogics & InteractorOutputLogics {
public var request: PublishRelay<Void> = .init()
public var response: Observable<String> {
return request
.flatMap({ [unowned self] _ -> Single<String> in
return self.worker.getTitle()
})
.asObservable()
}
private let worker: TestWorker
init(worker: TestWorker) {
self.worker = worker
}
}
/*
Interactor의 input과 output에 대한 RxTest진행
어떠한 Request 이벤트 발생시 기대하는 Response 이벤트를 받는지?
Worker는 Stub으로 생성하여 Interactor에 주입
*/
class InteractorTests: XCTestCase {
var interactor: Interactor!
var disposeBag: DisposeBag!
override func setUp() {
interactor =Interactor.init(worker: TestWorkerStub.init())
disposeBag = DisposeBag()
}
func testInteractor() {
let scheduler = TestScheduler.init(initialClock: 0)
let output = scheduler.createObserver(String.self)
// given
scheduler.createColdObservable([.next(100, ()), .next(200, ())])
.bind(to: interactor.request)
.disposed(by: disposeBag)
// when
interactor.response.subscribe(output)
.disposed(by: disposeBag)
// then
scheduler.start()
XCTAssertEqual(output.events, [.next(100, "hello"), .next(200, "hello")])
}
class TestWorkerStub: TestWorker {
override func getTitle() -> Single<String> {
return Single.just("hello")
}
}
}
protocol PresenterOutputLogics {
var display: Driver<String> { get }
}
class Presenter: PresenterOutputLogics {
public var display: Driver<String> {
// interactor의 response에 대한 error처리는 presenter에서
return interactor.response
.asDriver(onErrorJustReturn: "ERROR!")
}
private var interactor: InteractorOutputLogics
init(interactor: InteractorOutputLogics) {
self.interactor = interactor
}
}
/*
Presneter의 output에 대한 RxTest진행
InteractorOutputLogic에 대한 Stub을 생성해서 Presenter 주입
*/
class PresenterTests: XCTestCase {
var stub: InteractorOutputLogicsStub!
var presenter: Presenter!
var disposeBag: DisposeBag!
override func setUp() {
self.stub = InteractorOutputLogicsStub.init()
presenter = Presenter.init(interactor: stub)
disposeBag = DisposeBag()
}
func testPresenter() {
// Given
self.stub.isSuccess = true
// When
let output = try! presenter.display.toBlocking(timeout: 2.0).toArray()
// Then
XCTAssertEqual(output, ["test"])
}
func testPresenter2() {
// Given
self.stub.isSuccess = false
// When
let output = try! presenter.display.toBlocking(timeout: 2.0).toArray()
// Then
XCTAssertEqual(output, ["error"])
}
class InteractorOutputLogicsStub: InteractorOutputLogics {
var isSuccess: Bool = true
var response: Observable<String> {
return Observable.just(isSuccess ? "test": "error")
}
}
}
class ViewController {
var interactor: InteractorInputLogics!
var presenter: PresenterOutputLogics!
init() {
self.configureVIPCycle()
}
func configureVIPCycle() {
let interactor = Interactor.init(worker: .init())
self.interactor = interactor
self.presenter = Presenter.init(interactor: interactor)
}
}
@GeekTree0101
Copy link
Author

설계 Flow
Interactor -> Presenter -> ViewController or ViewController -> Interactor -> Presenter
반드시 Presenter보다 Interactor를 먼저 개발해야함.

@GeekTree0101
Copy link
Author

기존 Interactor의 output을 Presenter내부에서 binding처리 하지 않고 바로 Presenter Output Logic으로 반환

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment