У меня есть ряд тестов, которые начали давать сбой с тех пор, как я ввел DispatchGroup.
Пройдите простой тест, например:
func test_loading_indicator_is_visible_only_when_loading_profile() {
let (sut, spy) = makeSUT()
let profile = makeProfile()
let error = makeError()
sut.loadViewIfNeeded()
XCTAssertEqual(sut.isShowingLoadingIndicator, true)
spy.loadProfileCompletes(with: .failure(error))
XCTAssertEqual(sut.isShowingLoadingIndicator, false)
sut.simulateRefresh()
XCTAssertEqual(sut.isShowingLoadingIndicator, true)
spy.loadProfileCompletes(with: .success(profile), at: 1)
XCTAssertEqual(sut.isShowingLoadingIndicator, false)
}
- Показать индикатор загрузки при получении
- Скрыть при ошибке
- Потяните, чтобы обновить sh показать снова
- Скрыть при успехе
Это работает на 100% без DispatchGroup.
Мне нужно выполнить 2 асинхронных c задачи во время этой загрузки, поэтому я подумал, что группа диспетчеризации будет идеальной, так как я могу дождаться обоих блоков завершения, прежде чем уведомить докладчика об этой задаче.
Однако последнее утверждение всегда терпит неудачу, после некоторой отладки, которую я вижу в случае моего теста, событие успеха никогда не получено, что, в свою очередь, означает, что индикатор не удален.
Тем не менее, выполнение кода в производственном процессе, Я вижу, что это действительно работает, поэтому я думаю, что это, возможно, связано с запуском в тесте.
Я удалил вторую задачу asyn c, но оставил группу рассылки на месте, чтобы проверить, это что-то изменило и не изменило.
Для ясности, здесь была добавлена группа рассылки:
final class ProfileLoaderPresentationAdapter: ProfileRefreshViewControllerDelegate {
var presenter: ProfilePresenter?
private let profileLoader: ProfileLoader
init(profileLoader: ProfileLoader) {
self.profileLoader = profileLoader
}
func didRequestProfile() {
presenter?.didStartLoading()
profileLoader.load(then: { [weak self] result in
switch result {
case let .success(payload): self?.presenter?.didFinishLoading(with: payload.profile)
case let .failure(error): self?.presenter?.didFinishLoading(with: error)
}
})
}
}
Так что теперь это выглядит так:
final class ProfileLoaderPresentationAdapter: ProfileRefreshViewControllerDelegate {
var presenter: ProfilePresenter?
private let profileLoader: ProfileLoader
init(profileLoader: ProfileLoader) {
self.profileLoader = profileLoader
}
func didRequestProfile() {
let taskGroup = DispatchGroup()
var profile: Profile? = nil
presenter?.didStartLoading()
taskGroup.enter()
profileLoader.load(then: { [weak self] result in
switch result {
case let .success(payload): profile = payload.profile
case let .failure(error): self?.presenter?.didFinishLoading(with: error)
}
taskGroup.leave()
})
taskGroup.notify(queue: .main, execute: { [weak self] in
guard let self = self, let profile = profile else { return }
self.presenter?.didFinishLoading(with: profile)
})
}
}
Должен ли я делать что-то еще, чтобы убедиться, что я могу проверить этот код? У меня никогда не было этой проблемы раньше, но недавно я не проверял ее как mu sh, как сейчас (позор ... ..)
Edit
Мой шпион выглядит так:
class LoaderSpy: ProfileLoader {
enum Message: Equatable {
case loadProfile
}
private(set) var messages: [Message] = []
private var loadProfileCompletions: [(LoadProfileResult) -> Void] = []
func load(then completion: @escaping (LoadProfileResult) -> Void) {
messages.append(.loadProfile)
loadProfileCompletions.append(completion)
}
func loadProfileCompletes(with result: LoadProfileResult, at index: Int = 0) {
loadProfileCompletions[index](result)
}
}