在使用 MockTableView 時,這段代碼仍然沒有從模擬中呼叫 reloadData(),我想知道這里有什么問題。
跟隨本書:Test-Driven IOS Development with Swift 4 - 第三版
第164頁,我作為一個練習
完整的代碼倉庫 - 在 github
ItemListViewController.swift
import UIKit
class ItemListViewController: UIViewController, ItemManagerSettable {
@IBOutlet var tableView: UITableView!
@IBOutlet var dataProvider: (UITableViewDataSource & UITableViewDelegate &
ItemManagerSettable)!
var itemManager: ItemManager?
override func viewDidLoad() {
super.viewDidLoad()
itemManager = ItemManager()
dataProvider.itemManager = itemManager
tableView.dataSource = dataProvider
tableView.delegate = dataProvider
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
tableView.reloadData()
}
@IBAction func addItem(_ sender: UIBarButtonItem) {
if let nextViewController =
storyboard?.instantiateViewController(
withIdentifier: "InputViewController")
as? InputViewController {
nextViewController.itemManager = itemManager
present(nextViewController, animated: true, completion: nil)
}
}
}
ItemListViewControllerTest.swift
import XCTest
@testable import ToDo
class ItemListViewControllerTest: XCTestCase {
var sut: ItemListViewController!
var addButton: UIBarButtonItem!
var action: Selector!
override func setUpWithError() throws {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier:
"ItemListViewController")
sut = vc as? ItemListViewController
addButton = sut.navigationItem.rightBarButtonItem
action = addButton.action
UIApplication.shared.keyWindow?.rootViewController = sut
sut.loadViewIfNeeded()
}
override func tearDownWithError() throws {}
func testItemListVC_ReloadTableViewWhenAddNewTodoItem() {
let mockTableView = MocktableView()
sut.tableView = mockTableView
guard let addButton = sut.navigationItem.rightBarButtonItem else{
XCTFail()
return
}
guard let action = addButton.action else{
XCTFail()
return
}
sut.performSelector(onMainThread: action, with: addButton, waitUntilDone: true)
guard let inputViewController = sut.presentedViewController as?
InputViewController else{
XCTFail()
return
}
inputViewController.titleTextField.text = "Test Title"
inputViewController.save()
XCTAssertTrue(mockTableView.calledReloadData)
}
}
extension ItemListViewControllerTest{
class MocktableView: UITableView{
var calledReloadData: Bool = false
override func reloadData() {
calledReloadData = true
super.reloadData()
}
}
}
uj5u.com熱心網友回復:
你注入一個MockTableview然后你呼叫loadViewIfNeeded(). 但是因為這個視圖控制器是基于storyboard的,而table view是一個outlet,所以此時加載的是實際的table view。這取代了你的MockTableview.
一種解決方案是:
loadViewIfNeeded()先打電話- 注入
MockTableview替換實際的表視圖 - 直接打電話
viewDidLoad()。即使loadViewIfNeeded()已經呼叫它,我們現在需要重復它,因為我們有一個不同的 tableview。
另一種可能的解決方案:
- 完全避免
MockTableview。繼續使用真實的表格視圖。您可以通過檢查行數是否與更改的資料匹配來測驗它是否重新加載資料。
另一個解決方案:
- 避免故事板。您可以使用普通的 XIB(但這些缺少表格視圖原型單元格)或以編程方式執行此操作。
順便說一句,我看到你所有的tearDownWithError()實作都是空的。請務必拆除您設定的所有內容。否則,您最終將同時擁有多個正在測驗的系統實體。我在這里解釋:https ://qualitycoding.org/xctestcase-teardown/
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/509837.html
