Сбой тестирования при добавлении DispatchGroup - PullRequest
0 голосов
/ 08 апреля 2020

У меня есть ряд тестов, которые начали давать сбой с тех пор, как я ввел 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)
  }
  1. Показать индикатор загрузки при получении
  2. Скрыть при ошибке
  3. Потяните, чтобы обновить sh показать снова
  4. Скрыть при успехе

Это работает на 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)
    }
  }

...