【问题标题】:deinit called but the uint testing not finisheddeinit 调用但单元测试未完成
【发布时间】:2020-08-12 20:50:22
【问题描述】:

我正在尝试测试我的协调器流程,但子协调器deinit 在单元测试用例完成之前调用了

我的协调器类

public final class AppCoordinator: Coordinator {

        public var childCoordinators: [Coordinator] = []

        public var navigationController: UINavigationController
        var window: UIWindow?

        public init(window: UIWindow?) {
            self.window = window
            let secController =  SecController()
            self.navigationController = UINavigationController(rootViewController: secController)
            secController.delegate = self

        }
        public func start() {
            window?.rootViewController = navigationController
            window?.makeKeyAndVisible()
        }
    }

    extension AppCoordinator: SecControllerDelegate, SignInControllerDelegate {
        public func removeSingIn() {

            self.childCoordinators.removeFirst()
        }

        public func showSignIn() {
            let signInCoordinator = SignInCoordinator(navigationController: self.navigationController)
            signInCoordinator.delegate = self
            self.childCoordinators.append(signInCoordinator)
            signInCoordinator.start()

        }

}

单元测试类

class AppCoordinatorTests: XCTestCase {
    var coordinator: AppCoordinator!

    override func setUp() {
        super.setUp()
        coordinator = AppCoordinator(window: UIWindow())
    }

    override func tearDown() {
        coordinator = nil
        super.tearDown()
    }

    func testStartMethod() {
        coordinator.start()
        XCTAssertNotNil(coordinator.window?.rootViewController)
    }

    func testShowSignIn() {
        coordinator.showSignIn()
        XCTAssertFalse(coordinator.childCoordinators.isEmpty)
        XCTAssertTrue(coordinator.navigationController.visibleViewController is SignInController)
        }
}

当尝试测试testShowSignIn 时总是因为deinit 调用removeSingIn 函数而失败

public class SignInController: UIViewController {

    public weak var delegate: SignInControllerDelegate?

    public init() {

        super.init(nibName: nil, bundle: nil)
    }

    deinit {
        self.delegate?.removeSingIn()
    }

}

【问题讨论】:

  • 如何实例化SignInController
  • 登录登录协调器

标签: swift unit-testing xctestcase coordinator-pattern


【解决方案1】:

让我们回顾一下步骤:

  • testShowSignIn 调用coordinator.showSignIn(),其中coordinatorAppCoordinator
  • showSignIn() 实例化 SignInCoordinator,并将其委托设置为 AppCoordinator 实例。

现在我们到了重要的部分:

  • 我们到达showSignIn() 的末尾。 SignInCoordinator 超出范围,因此 Swift 将其销毁。

没有任何东西维护对SignInCoordinator 的引用。但是您想测试AppCoordinatorSignInCoordinator 之间的交互。代码正在与您作斗争,因为AppCoordinator 决定自行创建和销毁SignInCoordinator

您可以通过更改设计来测试它。你有几个选择。

选项 1:AppCoordinator 更改为具有返回 SignInCoordinator 的惰性计算属性。如果你对那个设计没问题,这可以工作。然后SignInCoordinator会继续存活,以便测试可以查询到它。这通过公开SignInCoordinator 提高了AppCoordinator 的可测试性。

选项 2:让测试创建一个 SignInCoordinator将其传递作为showSignIn() 的参数。然后SignInCoordinator 生命周期将完全在AppCoordinator 之外进行管理。

【讨论】:

  • 感谢您的回答,我正在尝试声明惰性属性 lazy var signInCoordinator: SignInCoordinator = { return SignInCoordinator(navigationController: self.navigationController) }() 并在 showSignIn 中使用它,但同样的问题
  • 尝试将 deinit 添加到 SignInCoordinator 以打印某些内容。然后运行一个测试。测试日志显示什么?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-09-14
  • 2013-03-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多