使用 XCTestCase 将项目插入到集合视图失败

Inserting items to collection view fail with XCTestCase

TL;DR

我制作了示例项目来显示错误。您可以从以下位置克隆或下载它:

https://github.com/JakubMazur/SO45820305

并尝试 运行 对方案 SO45820305Testing 进行测试。它会崩溃


问题:

我的应用程序中有负责分页列表的代码。每当有新数据出现并对其进行解析时,它都会将数据附加到我的 VC 中的模型并插入 UICollectionView:

func appendNewData(_ dataSet: [ExampleData]) {
    let currentItemsCount = self.collectionViewDataSet.count
    self.collectionViewDataSet.append(contentsOf: dataSet)
    var paths: [IndexPath] = [IndexPath]()
    for i in currentItemsCount...(currentItemsCount+dataSet.count-1) {
        paths.append(IndexPath(row: i, section: 0))
    }
    self.collectionView.performBatchUpdates({
        self.collectionView.insertItems(at: paths) /* crash on this line */
    }) { _ in
        //print("done")
    }
}

这在应用程序正常启动时效果很好。所以我想测试一下这个方法。所以我写了一个简单的测试:

func testAppendNewData() {
    self.viewController.collectionViewDataSet = [ExampleData]()
    self.viewController.collectionView.reloadData()
    let newDataSet = [ExampleData(), ExampleData()]
    self.viewController.appendNewData(newDataSet)
    ...
}

所以通过这个测试一步一步来是:

  1. 我的 collectionViewDataSet 中有 none 数据。对象已初始化但计数器应为 0
  2. 然后我创建了两个示例对象并尝试将其附加到我的模型中。
  3. 然后在这个测试中还有一些(断言检查成功添加的东西到模型)。但它在这里崩溃并出现错误:

error: -[Project.TestClass testAppendNewData] : failed: caught "NSInternalInconsistencyException", "Invalid update: invalid number of items in section 0. The number of items contained in an existing section after the update (2) must be equal to the number of items contained in that section before the update (2), plus or minus the number of items inserted or deleted from that section (2 inserted, 0 deleted) and plus or minus the number of items moved into or out of that section (0 moved in, 0 moved out)."

所以错误说我的项目计算错误,但实际上 must be equal to the number of items contained in that section before the update (2), 困扰我。这两项在更新前如何结束?有趣的是。它如何在生产应用程序中工作而不在测试框架中工作?

编辑: @fishinear 指出正确,我不应该在不重新加载数据的情况下更改内容,所以我更新了我的代码。现在和上面一样但仍然导致同样的问题

您正在更改数据源的完整内容,但没有告知集合视图:

self.viewController.collectionViewDataSet = [ExampleData]()

之后您应该调用 reloadData 来更新集合视图:

self.viewController.collectionViewDataSet = [ExampleData]()
self.viewController.collectionView.reloadData()

let newDataSet = [ExampleData(), ExampleData()]
self.viewController.appendNewData(newDataSet)

在测试期间,numberOfItemsInSection 不会在 self.collectionView.insertItems(at: paths) 之前调用,这就是您崩溃的原因。

解决方案放在self.viewController.collectionView.numberOfItems(inSection: 0)之前viewController.appendNewData(["a","b","c","d"])