2

ViewModel 有一个绑定到intap事件的输入(观察者)。这个观察者的类型是。UIButtonUIViewControllerAnyObserver<Void>

在我的单元测试中,这是我所期望的:

let correctValues: [Recorded<Event<Void>>] = Recorded.events(
       .next(0, ()),
       .completed(0)
   )

我的测试观察者定义是:

private var voidEventsObserver: TestableObserver<Void>!

let scheduler = TestScheduler(initialClock: 0)
voidEventsObserver = scheduler.createObserver(Void.self)

断言声明:

XCTAssertEqual(voidEventsObserver.events, correctValues)

我收到以下错误:

表达式类型 '()' 在没有更多上下文的情况下是模棱两可的

在 Rx 中,Void事件是正常的,要正确测试 ViewModel,需要比较它们。eg .next(0, ()), .completed(0)etc.Void不是Equatable,而且它没有意义Equatable。但是,我需要断言事件是.nextor.error还是.completed。我如何断言那部分?

4

1 回答 1

2

有时工作Void可能会很痛苦。

玩弄了您的示例,但是Equatable由于不是名义类型Result或由于这些类型已经与.EventVoidVoidEquatable

一种方法是做这样的事情:

XCTAssertEqual(voidEventsObserver.events.count, correctValues.count)

for (actual, expected) in zip(voidEventsObserver.events, correctValues) {
    XCTAssertEqual(actual.time, expected.time, "different times")

    let equal: Bool
    switch (actual.value, expected.value) {
    case (.next, .next),
         (.completed, .completed):
        equal = true
    default:
        equal = false
    }
    XCTAssertTrue(equal, "different event")
}

现在这很难看,很难阅读。另一种方法是引入包装器:

struct VoidRecord: Equatable {
    let record: Recorded<Event<Void>>

    static func == (lhs: Self, rhs: Self) -> Bool {
        guard lhs.record.time == rhs.record.time else { return false }

        switch (lhs.record.value, rhs.record.value) {
        case (.next, .next),
             (.completed, .completed):
            return true
        default:
            return false
        }
    }
}

XCTAssertEqual(
    voidEventsObserver.events.map(VoidRecord.init),
    correctValues.map(VoidRecord.init)
)

这读起来好多了。请注意,以上将.error事件视为始终不同。如果您需要比较错误事件,只需将此逻辑从 RxSwift 添加到上面的==函数中。

于 2019-12-24T11:56:05.700 回答