如何解决使用 TestScheduler 订阅序列时未获得所有预期事件
我正在尝试为使用 ReactorKit 和 Realm/RxRealm 构建的应用中的 Reactor
编写集成测试。
我在使用 TestScheduler
模拟用户操作和测试预期发出的状态时遇到问题。
简而言之,我的问题是:我正在绑定一个动作,让我的 Reactor 将一个项目保存到 Realm,我的 Reactor 也在 Realm 中观察到这个对象的变化,我希望我的 Reactor 发出新的状态从 Realm 观察到的此项。
我看到的是我的测试没有及时获得新保存的对象的发射来断言它的值,它是在我的测试断言运行后发射的。
涉及大量代码,但尝试将其缩减为一个独立的示例,大致如下所示:
struct MyObject {
var counter: Int = 0
}
class MyReactor: Reactor {
enum Action {
case load
case mutateState
}
enum Mutation {
case setobject(MyObject)
}
struct State {
var object: MyObject?
}
func mutate(action: Action) -> Observable<Mutation> {
switch action {
case .load:
return service.monitorObject().map(Mutation.setobject)
case .mutateState:
guard var myObject = currentState.object else { return .empty() }
myObject.counter += 1
return service.save(myObject).andThen(.empty())
}
}
func reduce(state: State,mutation: Mutation) -> Observable<State> {
var newState = state
switch mutation {
case let .setobject(object):
// Should be called twice in tests,once on load,once after mutateState action
newState.object = object
}
}
}
struct Service {
// There is always at least one default instance of `MyObject` in Realm.
func monitorObject() -> Observable<MyObject> {
return Observable
.collection(from: realm.objects(MyObject.self))
.map { $0.first! }
}
func save(_ object: MyObject) -> Completable {
return Completable.create { emitter in
try! realm.write {
realm.add(object,update: .modified)
}
emitter(.completed)
return disposables.create()
}
}
}
class MyTest: QuickSpec {
var scheduler: TestScheduler!
var sut: MyReactor!
var disposeBag: disposeBag!
var service: Service!
var config: Realm.Configuration!
override func spec() {
beforeEach {
config = Realm.Configuration(inMemoryIdentifier: UUID().uuidString)
scheduler = TestScheduler(initialClock: 0)
disposeBag = disposeBag()
sut = MyReactor()
service = Service(realmConfig: config)
}
describe("when my reactor gets a mutateState action") {
it("should mutate state") {
scheduler.createHotObservable([
.next(1,Action.load),.next(2,Action.mutateState),])
.bind(to: sut.action)
.disposed(by: disposeBag)
let response = scheduler.start(created: 0,subscribed: 0,disposed: 1000) {
sut.state.map(\.object)
}
// Counter always equals 0
XCTAssertTrue(response.events.last!.value.element!!.counter == 1)
}
}
}
}
我期望发生的是我的 Reactor 的状态在 XCTAssertTrue
被击中之前第二次设置。实际发生的是断言被初始加载状态命中,然后,我的反应器的状态再次设置。
我认为我的问题可能与调度程序有关。我尝试过将测试调度程序注入我的服务并在我的 observeOn(testScheduler)
函数上执行 monitorObject
。但是我仍然观察到在第二次设置反应器状态之前断言被击中。我也不确定 RxRealm/Realm 更改集通知的细微差别是否是原因 - 不确定如何验证是否是这种情况。
希望问题和疑问是清楚的。在此先感谢您的帮助。
解决方法
所以您正在尝试测试 Realm 是否有效。我不使用 Realm,但根据您的描述,它可能会更新内部线程上的对象,然后您会在后续循环中获得发射。
您可以使用 XCTestExpectation 对其进行测试。以下是 Apple 的文档:https://developer.apple.com/documentation/xctest/asynchronous_tests_and_expectations/testing_asynchronous_operations_with_expectations
但是请注意,如果 Realm 出现问题并且此测试失败,您将无能为力。
,我决定尝试编写集成测试比它的价值更麻烦,而且可能不会产生非常有用的测试。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。