我们如何为 swift ios 中的函数编写单元测试用例

How can we write Unit Test Case for the function in swift ios

我想为视图控制器中的委托方法之一的方法编写单元测试用例。我为 VC 创建了一个单元测试用例 class 并且正在尝试为该方法编写一个单元测试。

这是在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 创建了一个单元测试 class,并尝试按照委托方法未找到的几个教程正确编写它。

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")
   }
}