以编程方式实例化在UIViewController中测试UITableView

时间:2019-06-14 07:52:31

标签: swift uitableview xctest

我想将数据管理器注入视图控制器并对其进行测试。

ViewController:

class ViewController: UIViewController {

    @IBOutlet weak var tableView: UITableView!

    var alert: AlertViewController?

    var coreDataManager: CoreDataManagerProtocol?

    init(coreDataManager: CoreDataManagerProtocol) {
        self.coreDataManager = coreDataManager
        super.init(nibName: nil, bundle: nil)
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        self.coreDataManager = CoreDataManager()
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        tableView.register(UITableViewCell.self, forCellReuseIdentifier: "Cell")

    }

    @IBAction func addItem(_ sender: Any) {
        alert = UIStoryboard(name: Constants.alertStoryBoard, bundle: nil).instantiateViewController(withIdentifier: Constants.alerts.mainAlert) as? AlertViewController
        alert?.title = "Enter your task"
        alert?.presentToWindow()
        alert?.delegate = self
    }
}

extension ViewController: UITableViewDataSource {
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return coreDataManager?.getTasks().count ?? 0
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let data = coreDataManager?.getTasks()[indexPath.row]
        let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
        cell.textLabel?.text = data?.value(forKey: Constants.entityNameAttribute) as? String
        return cell
    }
}

我想通过在模拟中注入视图控制器来对此进行测试:

class CoreDataManagerMock: CoreDataManagerProtocol {
    var storeCordinator: NSPersistentStoreCoordinator!
    var managedObjectContext: NSManagedObjectContext!
    var managedObjectModel: NSManagedObjectModel!
    var store: NSPersistentStore!

    func getTasks() -> [NSManagedObject] {
        managedObjectModel = NSManagedObjectModel.mergedModel(from: nil)
        storeCordinator = NSPersistentStoreCoordinator(managedObjectModel: managedObjectModel)

        do {
            store = try storeCordinator.addPersistentStore(
                ofType: NSInMemoryStoreType, configurationName: nil, at: nil, options: nil)
        } catch {
            // catch failure here
        }
        managedObjectContext = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType)
        managedObjectContext.persistentStoreCoordinator = storeCordinator

        var localTasks = [NSManagedObject]()
        let entityOne = NSEntityDescription.insertNewObject(forEntityName: Constants.entityName, into: managedObjectContext)
        entityOne.setValue(false, forKey: Constants.entityCompletedattribute)
        entityOne.setValue("Enter your task", forKey: Constants.entityNameAttribute)
        localTasks.append(entityOne)
        return localTasks
    }

    func save(task: String) {
        //
    }

}

但我正在努力对此进行测试。

我无法请求一个单元,因为我没有从情节提要中实例化(而且我不能,因为我需要注入模拟核心管理器。

在每次尝试运行tableView的测试中,解析为nil

这是我的尝试,认为我可以直接测试cellForRowAt函数:

    func testtv() {
        let CDM = CoreDataManagerMock()
        let viewController = ViewController(coreDataManager: CDM)

       viewController.tableView.register(UITableViewCell.self, forCellReuseIdentifier: "Cell")

        viewController.tableView(UITableViewMock(), cellForRowAt: IndexPath(row: 0, section: 0))

        let actualCell = viewController.tableView?.cellForRow(at: IndexPath(row: 0, section: 0) )


        let test = viewController.tableView(UITableViewMock(), cellForRowAt: IndexPath(row: 0, section: 0))
        XCTAssertEqual(actualCell?.textLabel?.text, actualCell?.textLabel?.text)
    }

但是由于tableView为nil为nil,所以我无法注册该单元格。我如何测试cellForRow(at:当我如上所述注入依赖项时?

1 个答案:

答案 0 :(得分:0)

通过这样做,我如何对实例化UIStoryboard的{​​{1}}进行测试。

UIViewController

所以在您的情况下,因为这是代码的样子:

// STEP 1
// instantiate the storyboard
let storyboard = UIStoryboard(name: "SomeStoryboard", bundle: nil)

// STEP 2
// instantiate the UIViewController using the storyboard
let sampleViewController = storyboard.instantiateViewController(withIdentifier: "SampleViewController") as! SampleViewController

// STEP 3
// set the properties you need to set 
sampleViewController.xxxxx = "foo"
sampleViewController.yyyyy = "bar"

// STEP 4
// call the view so the ui objects would be instantiated
// not doing this would cause a crash
// this also calls `viewDidLoad()`
_ = sampleViewController.view

ViewController

这是因为调用func testtv() { let storyboard = UIStoryboard(name: "INSERT STORYBOARD NAME HERE", bundle: nil) let viewController = storyboard.instantiateViewController(withIdentifier: "ViewController") as! ViewController viewController.coreDataManager = CoreDataManagerMock() _ = viewController.view // I'm not sure about the code below this comment // but the above code should work viewController.tableView(UITableViewMock(), cellForRowAt: IndexPath(row: 0, section: 0)) let actualCell = viewController.tableView?.cellForRow(at: IndexPath(row: 0, section: 0) ) let test = viewController.tableView(UITableViewMock(), cellForRowAt: IndexPath(row: 0, section: 0)) XCTAssertEqual(actualCell?.textLabel?.text, actualCell?.textLabel?.text) } 使用instantiateViewController(withIdentifier: _)

您可以在下面删除此代码段,因为您不需要它,而且由于您要实例化的init?(coder aDecoder: NSCoder)来自情节提要,因此该代码段也无效。

UIViewController

您可以做的是创建一个静态方法,用您需要的参数实例化init(coreDataManager: CoreDataManagerProtocol) { self.coreDataManager = coreDataManager super.init(nibName: nil, bundle: nil) } 。示例:

UIViewController