【问题标题】:Swift MVVM testing strategy and code coverage questionsSwift MVVM 测试策略和代码覆盖率问题
【发布时间】:2017-08-31 00:54:51
【问题描述】:

我在使用 Xcode 为 MVVM 环境中的视图模型生成代码覆盖率时遇到了问题。

我们的基本设置是视图控制器向视图模型发出请求,然后视图模型调用与 Web 服务对话的数据管理器上的方法。

我想出了一种我认为是相当优雅的方法来测试视图模型,方法是创建一个假数据管理器,它继承了实际数据管理器并覆盖了 VM 调用的函数。

问题在于,要使其正常工作,VM 必须是应用程序目标和测试目标的一部分。这样做的一个明显副作用是,即使单元测试通过,也不会为属于两个或多个目标的项目生成代码覆盖率。项目中启用了代码覆盖率。

这是一个摘录的视图模型:

import Foundation

class BoosViewModel: BaseViewModel {
    convenience override init()  {
        self.init(dataManager: BoosDataManager(), andModel: nil)
    }

    func getUnlinkedBoos(_ cardType: CardType) {
        (dataManager as! BoosDataManager).getUnlinkedBoos(cardType) { result, error in
            ...stuff happens here...
        }
    }
}

...和数据管理器

class BoosDataManager: DataManager {

    static let SharedInstance: BoosDataManager = {
        var manager = BoosDataManager()
        return manager
    }()

    func getUnlinkedBoos(_ cardType: CardType = .loyalty, completion: @escaping ((_ result: BoosModel?, _ error: NSError?) -> Void)) {
        ...stuff happens here...
    }
}

...和测试

class BoosViewModelTests: XCTestCase {

    func testGetUnlinkedBoosHappyPath() {
        class FauxDataManager: BoosDataManager {
            override func getUnlinkedBoos(_ cardType: CardType = .loyalty, completion: @escaping ((_ result: BoosModel?, _ error: NSError?) -> Void)) {
                ...stuff happens here...
            }
        }

        let viewModel = BoosViewModel()
        let dataManager = FauxDataManager()

        viewModel.dataManager = dataManager
        viewModel.getUnlinkedBoos(.loyalty)
        XCTAssertTrue(testObserver.updated)
        XCTAssertEqual(testObserver.newViewModel.getBoos().count, 1)
    }
}

如前所述,此场景中的单元测试成功完成,但未生成单元覆盖率。

我有较旧的测试,其中我实际上创建了一个外部假数据管理器类供测试使用,被测类不是测试目标的一部分,并且覆盖工作正常。

这样做的缺点是我必须创建多个数据管理器来处理返回的特定情况。如果我不能封装这些类,我需要创建一堆快速数据管理器,每个场景一个。

这就是我想出内部类的原因。

现在,如果我从测试目标中删除正在测试的视图模型,就会出现问题。完成此操作后,我将 @testable import BoosApp 添加到单元测试中,以便可以解析被测视图模型。当我这样做时,我收到以下错误:

无法将“BoosTests.BoosViewModelTests.(testGetUnlinkedBoosHappyPath () -> ()).(FauxDataManager #1)”(0x11f673d18) 类型的值转换为“Boos.BoosDataManager”(0x10444b128)。 8 月 30 日 20:43:01 Pay[19025]:无法将类型“BoosTests.BoosViewModelTests.(testGetUnlinkedBoosHappyPath () -> ()).(FauxDataManager #1)”(0x11f673d18) 的值转换为“Boos.BoosDataManager”(0x10444b128) )。

我不确定我错过了什么。有没有办法让这个场景工作,还是我被困在测试代码之外创建多个数据管理器?

【问题讨论】:

    标签: swift xcode unit-testing mvvm mocking


    【解决方案1】:

    最终,我发现主要问题是视图模型和数据管理器以某种方式添加到了测试目标中。从测试目标中删除它们后,我能够进行一些小的更改,并且一切运行正常。仅供参考。

    【讨论】:

      猜你喜欢
      • 2013-04-16
      • 1970-01-01
      • 2020-04-29
      • 1970-01-01
      • 2021-02-08
      • 2012-01-18
      • 1970-01-01
      • 1970-01-01
      • 2023-03-04
      相关资源
      最近更新 更多