I am using storyboard and I have the outlet created into View controller.In view did load I have setup the delegate and datasource to self . I am trying to write unit test for Table view Outlet but Actually, It return nil although, it exists..
Here is the view model code ..
class CakeListViewModel: CakeListViewModelType {
weak private var delegate: CakeListViewType!
let service:Service!
private var cakes:[Cake]?
var itemCount: Int {
return cakes?.count ?? 0
}
init(delegate: CakeListViewType,
service:Service = ServiceImpl()) {
self.delegate = delegate
self.service = service
}
/*
this method connect calls rest API to get data
*/
func fetchCakes() {
let client = ServiceClient(baseUrl:EndPoints.baseUrl.rawValue, path:Path.cakeList.rawValue, params:"", method:"get")
service.fetchData(client:client, type:Cake.self) { [weak self] (result) in
switch result {
case .success(let result):
self?.cakes = result
DispatchQueue.main.async {
self?.delegate?.updateUI()
}
case .failure(_):
self?.cakes = nil
DispatchQueue.main.async {
self?.delegate?.showError()
}
}
}
}
}
Here is my test code ..
class CakeViewModelTest: XCTestCase {
var mockService:MockService!
var viewModel:CakeListViewModel!
override func setUp() {
mockService = MockService()
let vc = CakeListViewController()
viewModel = CakeListViewModel(delegate:vc, service:mockService)
}
func testTableViewOutlet() {
let vc = CakeListViewController()
XCTAssertNotNil(vc.tableView)
}
}
Here is my view controller code ..
class CakeListViewController: UIViewController {
@IBOutlet var tableView: UITableView!
var viewModel:CakeListViewModelType!
weak var coordinator: Coordinator?
override func viewDidLoad() {
super.viewDidLoad()
tableView.dataSource = self
tableView.delegate = self
title = "🎂CakeItApp🍰"
viewModel.fetchCakes()
}
}
Here is the screenshot of the error ..
The view controller initializer you are using does make any use of the storyboard. So nothing you've setup in the storyboard (outlets, constraints, etc.) will exist in the view controller. You need to replace the line:
let vc = CakeListViewController()
with code more like this:
if let vc = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "YourViewControllerID") as? CakeListViewController {
}
Replace "Main"
with the name of your storyboard (if it isn't actually "Main").
Replace "YourViewControllerID"
with the actual ID you gave the view controller in the storyboard.
With that fixed, you will run into more issues. Your CakeListViewController
has an implicitly unwrapped optional named viewModel
that is accessed in viewDidLoad
. So you must ensure that you set viewModel
immediately after creating the view controller.
if let vc = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "YourViewControllerID") as? CakeListViewController {
vc.viewModel = someViewModelInstance
// Do your tests here
}