Reactorのtransform内でPublishSubjectをマップした挙動をテストした際にハマったこと


transform(mutation:)内の処理

以下のようにeventをマップしたReactor内のtransformの挙動をテストする際につまづいたポイントを書き残しておきます。

import ReactorKit
import RxSwift

final class HogeReactor: Reactor {
    ...
    func transform(mutation: Observable<Mutation>) -> Observable<Mutation> {
        return .merge(
            mutation,
            provider.accountService.event.flatMap { event -> Observable<Mutation> in
                switch event {
                case let .updateProfile(user):
                    return .just(.setUser(user))
                }
            }
        )
    }
    ...
}

eventの実装

ちなみにprovider.accountService.eventは以下のようにPublishSubjectで実装されています。

enum AccountEvent {
    case updateProfile(user: User)
}

protocol AccountServiceType {
    var event: PublishSubject<AccountEvent> { get }
    ...
}

final class AccountService: AccountServiceType {
    let event = PublishSubject<AccountEvent>()
    ...
}

テスト失敗

これをテストする際に単純にstreamを流しただけだとテストがうまくいきませんでした。

@testable import Hoge
import Nimble
import Quick

class HogeReactorSpec: QuickSpec {
    ...
    describe("state.user") {
        context("when receives updateProfile event", closure: {
            it("is updated user", closure: {
                let updatedUser = TestData.testUser()
                stubServiceProvider.accountService.event.onNext(.updateProfile(user: updatedUser))

                // Failed:stateにupdatedUserがセットされず
                expect(hogeReactor.currentState.user) == updatedUser  
            })
        })
    }
}

一度もtransform(mutation:)が呼ばれてないため、eventのマップがそもそもできていないのが原因ぽいです。

テスト通過

transform(mutation:)を呼ぶために適当にactionを呼んでやるとうまくいきました。

@testable import Hoge
import Nimble
import Quick

class HogeReactorSpec: QuickSpec {
    ...
    describe("state.user") {
        context("when receives updateProfile event", closure: {
            it("is updated user", closure: {
                // NOTE: Call any action to set up transformed mutation
                hogeReactor.action.onNext(.load)

                let updatedUser = TestData.testUser()
                stubServiceProvider.accountService.event.onNext(.updateProfile(user: updatedUser))

                // Pass:stateにupdatedUserがセットされる
                expect(hogeReactor.currentState.user) == updatedUser
            })
        })
    }
}

本当にこれが正しいのかわかりませんが、とりあえず動いたので良しとしてます。
知見ある方いましたらコメントで教えていただけると嬉しいです。