我想为这个方法写一个单元测试用例它是视图控制器中的一个委托方法。我为VC创建了一个单元测试用例类,并试图为该方法编写一个单元测试。
下面是用VC实现的方法。我们如何编写单元测试用例?
extension DownloadBaseViewController:EMPDecisionTreeCoordinatorDelegate {
func decisionEmptyTreeFeedbackButtonTapped() {
if let feedbackNavVc = storyboard?.instantiateViewController(identifier: "PremiumFeedbackNavViewController") as? PremiumCustomNavigationController {
if let feedbackVc = feedbackNavVc.children.first as? PremiumFeedbackViewController {
feedbackVc.id = self.fileDetails?.id
self.decesiontreeCoordinator!.rootViewController.present(feedbackNavVc, animated: true, completion: nil)
}
}
}
}
为VC创建了一个单元测试类,但无法按照委托方法的一些教程正确编写。
import XCTest
class DownloadBaseViewControllerTests: XCTestCase {
var downloadBaseViewController: DownloadBaseViewController!
func testDecisionEmptyTreeFeedbackButtonTapped() throws {
let feedbackVCNavigation = downloadBaseViewController.decisionEmptyTreeFeedbackButtonTapped
XCTAssertNotNil(feedbackVCNavigation, "Download base view controller contains feedback view controller and succesfully able to navigate")
///Test case Build succeded but this is not the way to test it properly need heads up on this.
}
override func setUpWithError() throws {
// Put setup code here. This method is called before the invocation of each test method in the class.
}
}
在你的应用中重构DownloadBaseViewController
,这样你就可以模拟依赖了:
extension DownloadBaseViewController:EMPDecisionTreeCoordinatorDelegate {
// Add this variable in DownloadBaseViewController
lazy var presentingController: ViewControllerPresenting? = self.decesiontreeCoordinator?.rootViewController
func decisionEmptyTreeFeedbackButtonTapped() {
if let feedbackNavVc = storyboard?.instantiateViewController(identifier: "PremiumFeedbackNavViewController") as? PremiumCustomNavigationController {
if let feedbackVc = feedbackNavVc.children.first as? PremiumFeedbackViewController {
feedbackVc.id = self.fileDetails?.id
self.presentingController?.present(feedbackNavVc, animated: true, completion: nil)
}
}
}
}
// You need this to mock the foreign dependency on UIViewController
protocol ViewControllerPresenting: AnyObject {
func present(_ viewControllerToPresent: UIViewController,
animated flag: Bool,
completion: (() -> Void)?)
}
extension UIViewController: ViewControllerPresenting {}
在测试中注入一个Spy对象,它将帮助您验证正确的行为:
final class UIViewControllerSpy: ViewControllerPresenting {
var viewControllerToPresent: UIViewController!
func present(_ viewControllerToPresent: UIViewController,
animated flag: Bool,
completion: (() -> Void)? = nil) {
self.viewControllerToPresent = viewControllerToPresent
}
}
class DownloadBaseViewControllerTests: XCTestCase {
var downloadBaseViewController: DownloadBaseViewController! = DownloadBaseViewController()
func testDecisionEmptyTreeFeedbackButtonTapped() throws {
// Given
let spyController = UIViewControllerSpy()
downloadBaseViewController.presentingController = spyController
// When
downloadBaseViewController.decisionEmptyTreeFeedbackButtonTapped()
// Then
let presentedController = spyController.viewControllerToPresent as? PremiumFeedbackViewController
XCTAssertNotNil(presentedController, "Download base view controller contains feedback view controller and succesfully able to navigate")
}
}