首页 > 解决方案 > Swift:在 ViewController 中为私有函数创建单元测试

问题描述

我正在尝试测试我的视图控制器,但我不确定如何测试其中的私有功能。它说是私人的。显然我可以将其公开,但这似乎违背了目的......

   import Quick
    import Nimble
    @testable import Recur

class ProfileDetailVCSpec: QuickSpec {
    class TestProfileDetailVC: ProfileDetailVC {
        var isProfileUpdated = false

        override func updateProfile() {
            isProfileUpdated = true
        }
        func pressDone() {
            doneButtonPressed() //COMPILER WON'T ALLOW, BECAUSE IT'S PRIVATE
        }
    }
    override func spec() {
        var testProfileDetailVC: TestProfileDetailVC!
        beforeEach {
            testProfileDetailVC = TestProfileDetailVC()
        }
        describe("edit profile") {
            context("user makes changes to name") {
                it("should call updateProfile") {
                    testProfileDetailVC.nameTextFieldValidInputEntered(ProfileEditNameView(), "TestFirst", "TestLast")
                    testProfileDetailVC.pressDone()
                    expect(testProfileDetailVC?.isProfileUpdated).to(equal(true))
                }
            }
            context("user makes changes to photo") {
                it("should call updateProfile") {
                    testProfileDetailVC.nameTextFieldValidInputEntered(ProfileEditNameView(), "TestFirst", "TestLast")
                    testProfileDetailVC.pressDone() 
                    expect(testProfileDetailVC?.isProfileUpdated).to(equal(true))
                }
            }
            context("user doesn't make any changes") {
                it("should not call updateProfile") {
                    testProfileDetailVC.pressDone()
                    expect(testProfileDetailVC?.isProfileUpdated).to(equal(false))
                }
            }
        }
    }
}

这是视图控制器。我的同事仍在研究一些逻辑,但大部分都在那里。我似乎无法快速调用私有函数,所以我无法运行这些测试

class ProfileDetailVC: UIViewController {
    private let doneButton: UIButton = {
        let button = UIButton(type: .system)
        button.setTitle("Done", for: .normal)
        button.titleLabel?.font =  UIFont(name: "SFCompactRounded-Semibold", size: 16)
        button.tintColor = .recurBlue
        button.addTarget(self, action: #selector(doneButtonPressed), for: .touchUpInside)
        return button
    }()

    let profileNameEditView = ProfileEditNameView()
    let errorLabel: UILabel = {
        let label = UILabel()
        label.textColor = .red
        label.font = .regularSubtitle
        return label
    }()

    override func viewDidLoad() {
        super.viewDidLoad()
        loadProfileImage()
        setupUI()
        profileNameEditView.delegate = self
    }

    func updateProfile() {

    }

    private func loadProfileImage() {
        if let profile = Profile.currentProfile {
            profileImage.configure(with: profile, imageSize: CGSize(width: 120, height: 120))
        }
    }

    @objc private func doneButtonPressed() {
        updateProfile()
    }

extension ProfileDetailVC: ProfileEditNameViewDelegate {
    func nameTextFieldNonValidInputEntered(_: ProfileEditNameView) {
        errorLabel.text = "First and last name required"
    }

    func nameTextFieldValidInputEntered(_: ProfileEditNameView, _ firstNameText: String, _ lastNameText: String) {
        errorLabel.text = ""
    }
}

标签: swiftunit-testingtestingviewcontroller

解决方案


无法访问私有函数进行测试。但是,您使用的@testable属性将允许您在测试中使用内部函数。因此,您可以删除 private 关键字,并且 func 将默认为internal因为类是internal


推荐阅读