ReactorKit 공부하기 #2
해당 문서는 ReactorKit 3.2.0을 기준으로 작성.
이번에는 테스트코드를 작성해볼 예정
들어가기 전
RxTest는 반드시 CocoaPod에서 Tests쪽으로 타겟을 잡아주기!
테스팅
ReactorKit의 경우에는 테스트를 위한 함수가 내장되어 있어서, 손쉽게 view와 reacotr 둘 다 테스트 가능.
그렇다면 무엇을 테스트 해야하냐면 총 3가지를 테스트하면 좋음
- View
- Action :: 주어진 유저의 상호작용에 따라 적절한 action이 reactor로 보내지는가?
- State :: 주어진 state에서 view의 변수가 적절하게 set(저장) 되는가?
- Reactor
- State :: action에 따라 state가 적절하게 변경되었는가?
리액터킷 테스트코드
//
// ReactorKitPracticeTests.swift
// ReactorKitPracticeTests
//
// Created by Hamlit Jason on 2022/07/23.
//
import XCTest
@testable import ReactorKitPractice
import RxTest
import RxSwift
class ReactorKitPracticeTests: XCTestCase {
override func setUp() {
}
override func tearDownWithError() throws { }
// MARK: - View -> Reactor
// View에서 Reactor Action을 잘 넘기는지 테스트
func test_Action_View_to_Reactor() {
// given
let reactor = CounterViewReactor()
let viewController = CounterViewController()
reactor.isStubEnabled = true
viewController.reactor = reactor
// when
viewController.increaseButton.sendActions(for: .touchUpInside)
XCTAssertEqual(reactor.stub.actions.last, .increase)
// then
viewController.decreaseButton.sendActions(for: .touchUpInside)
XCTAssertEqual(reactor.stub.actions.last, .decrease)
}
// MARK: - Reactor -> View
// Reactor에서 변경된 상태(State)가 View에도 정상적으로 반영되는지 확인.
func test_State_Reactor_to_View() {
// given
let reactor = CounterViewReactor()
let viewController = CounterViewController()
reactor.isStubEnabled = true
viewController.reactor = reactor
// when
reactor.stub.state.value = CounterViewReactor.State(value: 0, isLoading: true)
// then
XCTAssertEqual(viewController.loadingIndicator.isAnimating, true)
XCTAssertEqual(viewController.countLabel.text, "0")
}
// MARK: - Reactor
// action을 받으면 비지니스 로직(Mutation)이 잘 처리되어 State값이 기대값으로 변하는지 확인.
func test_Reactor() {
let reactor = CounterViewReactor()
let expectation = XCTestExpectation()
expectation.expectedFulfillmentCount = 1
// when
reactor.action.onNext(.increase)
// then
XCTAssertEqual(reactor.currentState.isLoading, true)
}
}
실패한 테스트코드
테스트 코드를 실패했을 때를 기록
- 문제상황
- isLoading의 경우에는 false -> true(딜레이 1초) -> false로 결과가 방출되어야할 것 같은데, false -> true만 내려오고 있었음
- 딜레이 처리를 잘못한 것이 원인이 아닐까 생각하고 있으나, 원인을 잘 모르겠어서 ㅜㅜ 우선 기록
// 실패한 테스트 코드
// 작성일: 2022년 7월 25일
// 원인: delay의 문제로 보이나, 어떻게 해결할지 아직 잘 모르겠음.
// (문제 해결을 위해 시도해본 방법)
// 1. DispatchQueue를 활용
// 2. expectation 활용
func test_isLoading() {
let scheduler = TestScheduler(initialClock: 0)
let reactor = CounterViewReactor()
let disposeBag = DisposeBag()
scheduler.createHotObservable([
.next(100, .increase),
])
.subscribe(reactor.action)
.disposed(by: disposeBag)
// then
let response = scheduler.start(created: 0, subscribed: 0, disposed: 1000) {
reactor.state.map(\.isLoading)
}
XCTAssertEqual(response.events.map(\.value.element), [
false, // initial state
true, // 값 변경 .isLoading
false // 딜레이 후 isLoading
])
}
'apple > RxSwift, ReactorKit' 카테고리의 다른 글
[ReactorKit] ReactorKit 공부하기 #4 RxTodo 따라잡기 (2) (0) | 2022.09.08 |
---|---|
[ReactorKit] ReactorKit 공부하기 #3 RxTodo 따라잡기 (1) (0) | 2022.09.07 |
[ReactorKit] ReactorKit 공부하기 #1 (0) | 2022.07.24 |
RxSwift Signal,Emit (0) | 2022.02.19 |
iOS RxAction (RxSwift Community) (0) | 2022.01.19 |