Есть ли способ получить значение издателя PassthroughSubject в модульном тесте? Я хочу проверить, что функция возвращает успех, и чтобы проверить это, я хочу видеть, когда значение издателя .loaded, тогда успех.
class HomeViewModel: ObservableObject {
var homeState = PassthroughSubject<StatePublisher, Never>()
func load(item: HomeModel) {
self.homeState.send(.loading)
self.dataSource.load(item: item) { result in
switch result {
case .success:
self.homeState.send(.loaded)
case let .failure(error):
self.homeState.send(.error(message: error.localizedDescription))
}
}
}
}
class HomeViewModelTests: XCTestCase {
var sut: ViewModel!
var subscriptions = Set<AnyCancellable>()
override func setUpWithError() throws {
sut = ViewModel()
}
override func tearDownWithError() throws {
sut = nil
subscriptions = []
}
func testUpdateHomeSuccess() {
let expected = StatePublisher.loaded
var result = StatePublisher.loading
sut.load(item: HomeModel.fixture())
sut.homeState
.sink(receiveValue: { state in
result = state
})
.store(in: &subscriptions)
XCTAssert(
result == expected,
"Home expected to be \(expected) but was \(result)"
)
}
}
Пробовал вот такой тест, но сток ни разу не вызывается.





Предположительно, dataSource.load работает асинхронно. Это означает, что вам нужно использовать XCTestExpectation в вашем тестовом примере. Кроме того, поскольку вы используете PassthroughSubject, а не CurrentValueSubject, вы должны создать свою подписку перед при запуске загрузки, чтобы быть уверенным, что вы не пропустите ни одного опубликованного значения.
let ex = XCTestExpectation()
sut.homeState
.sink {
if case .loaded = $0 {
ex.fulfill()
}
}
.store(in: &subscriptions)
wait(for: [ex], timeout: 10)
// Test fails if it doesn't call `ex.fulfill()` within 10 seconds.
Прочтите руководство Apple по Тестирование асинхронных операций с ожиданиями.
Семантически именно то, что сказал Роб, но вы, вероятно, найдете синтаксический сахар пакета «CombineExpectations» сладким: github.com/groue/CombineExpectations
Фреймворк Combine является асинхронным. Вы должны использовать асинхронный тест!