单元测试 UICollectionView.indexPath(针对:UICollectionViewCell)
Unit Testing UICollectionView.indexPath(for: UICollectionViewCell)
我正在尝试在 ViewController
中对这段代码进行单元测试
func categoryTextEditedAt(_ cell: UICollectionViewCell, _ text: String) {
guard let indexPath = self.collectionView.indexPath(for: cell), text != "" else {return}
//Rest of the codes to be tested
}
而在我的单元测试中测试上面的功能如下:
func testCategoryTextEditedAt() {
sut.viewDidLoad()
sut.collectionView.reloadData()
let cell = sut.collectionView.dataSource?.collectionView(sut.collectionView, cellForItemAt: IndexPath(item: 0, section: 0))
sut.categoryTextEditedAt(cell!, "testString")
}
但我一直在为 categoryTextEditedAt(:)
函数中的 indexPath
获取 'nil'。在调试时,我发现 testCategoryTextEditedAt()
单元格内部有一个值,但 self.collectionView.indexPath(for:cell)
一直返回 'nil' for 'indexPath.'
我该如何进行这个过程?
我猜你的问题是因为你试图在错误的地方测试代码。
想象一下,如果你必须测试一个单元函数,你需要实例化所有 UICollection
结构,这是一种难闻的气味。
例如,您可以这样做。
enum UseCaseError {
textEmpty
}
class UseCase {
private let index: Int
private let text: String
init(index: Int, text: String) {
self.index = index
self.text = text
}
public func execute() throws {
guard text.isEmpty == false else {
throw UseCaseError.textEmpty
}
// your logic here to be tested
}
}
查看此 UseCase
,您可以测试何时 text
为空以及您所有的业务逻辑
现在你只需要将它放入categoryTextEditedAt
方法
func categoryTextEditedAt(_ cell: UICollectionViewCell, _ text: String) {
guard let indexPath = self.collectionView.indexPath(for: cell) { return }
try? UseCase(index: indexPath.item, text: text).execute()
}
如果您将代码分开,您可以在之前对其进行测试,并且您无需浪费时间尝试使 UIKit
函数正常工作,只需您的逻辑即可。
希望对这个例子有所帮助。
对于那些对如何对 collectionViewDelegateMethod 进行单元测试感到好奇的人:
func categoryTextEditedAt(_ cell: UICollectionViewCell, _ text: String) {
guard let indexPath = self.collectionView.indexPath(for: cell), text != "" else {return}
//Rest of the codes to be tested
}
你可以做类似
func testCategoryTextEditedAt() {
class MockCV: UICollectionView {
override func indexPath(for cell: UICollectionViewCell) -> IndexPath? {
let anyIndexPathWhichEverYoulike = IndexPath(item:0, section:0)
return anyIndexPathWhichEverYoulike
}
}
sut.collectionView = MockCV()
let cell = sut.collectionView.dataSource?.collectionView(sut.collectionView, cellForItemAt: IndexPath(item: 0, section: 0))
sut.categoryTextEditedAt(cell!, "testString")
}
我正在尝试在 ViewController
func categoryTextEditedAt(_ cell: UICollectionViewCell, _ text: String) {
guard let indexPath = self.collectionView.indexPath(for: cell), text != "" else {return}
//Rest of the codes to be tested
}
而在我的单元测试中测试上面的功能如下:
func testCategoryTextEditedAt() {
sut.viewDidLoad()
sut.collectionView.reloadData()
let cell = sut.collectionView.dataSource?.collectionView(sut.collectionView, cellForItemAt: IndexPath(item: 0, section: 0))
sut.categoryTextEditedAt(cell!, "testString")
}
但我一直在为 categoryTextEditedAt(:)
函数中的 indexPath
获取 'nil'。在调试时,我发现 testCategoryTextEditedAt()
单元格内部有一个值,但 self.collectionView.indexPath(for:cell)
一直返回 'nil' for 'indexPath.'
我该如何进行这个过程?
我猜你的问题是因为你试图在错误的地方测试代码。
想象一下,如果你必须测试一个单元函数,你需要实例化所有 UICollection
结构,这是一种难闻的气味。
例如,您可以这样做。
enum UseCaseError {
textEmpty
}
class UseCase {
private let index: Int
private let text: String
init(index: Int, text: String) {
self.index = index
self.text = text
}
public func execute() throws {
guard text.isEmpty == false else {
throw UseCaseError.textEmpty
}
// your logic here to be tested
}
}
查看此 UseCase
,您可以测试何时 text
为空以及您所有的业务逻辑
现在你只需要将它放入categoryTextEditedAt
方法
func categoryTextEditedAt(_ cell: UICollectionViewCell, _ text: String) {
guard let indexPath = self.collectionView.indexPath(for: cell) { return }
try? UseCase(index: indexPath.item, text: text).execute()
}
如果您将代码分开,您可以在之前对其进行测试,并且您无需浪费时间尝试使 UIKit
函数正常工作,只需您的逻辑即可。
希望对这个例子有所帮助。
对于那些对如何对 collectionViewDelegateMethod 进行单元测试感到好奇的人:
func categoryTextEditedAt(_ cell: UICollectionViewCell, _ text: String) {
guard let indexPath = self.collectionView.indexPath(for: cell), text != "" else {return}
//Rest of the codes to be tested
}
你可以做类似
func testCategoryTextEditedAt() {
class MockCV: UICollectionView {
override func indexPath(for cell: UICollectionViewCell) -> IndexPath? {
let anyIndexPathWhichEverYoulike = IndexPath(item:0, section:0)
return anyIndexPathWhichEverYoulike
}
}
sut.collectionView = MockCV()
let cell = sut.collectionView.dataSource?.collectionView(sut.collectionView, cellForItemAt: IndexPath(item: 0, section: 0))
sut.categoryTextEditedAt(cell!, "testString")
}