我有一个ViewController类,该类提供了一系列两个选择的弹出视图。每个两个选择的弹出视图都不同。
Popup1-Choice1-> Choice1Popup
Popup1-Choice2-> Choice2Popup
我打算将Popup1呈现为公开的方法,但我希望将Choice1Popup和Choice2Popup呈现为其他的方法是私有的。
如果我决定需要测试Choice1Popup和Choice2Popup,那么我可能必须将它们设置为内部而不是私有的,但是不太可能在其他任何地方使用它们。
我想编写一个单元测试,该测试测试何时按下了显示Choice1Popup的方法的Choice1按钮。我使用了带有方法类型变量的协议,以允许Mock注入弹出演示者的Mock版本。我对自己的方法感到不满意100%,因此我想就是否有更好的方法获得意见。
顺便说一句,我感到内部与私人之间存在冲突。能够测试我的私有方法会很好,但是我不希望它们能够在除单元测试之外的任何地方被调用,并使它们在内部公开。
这是代码,底部是一个单元测试:
// protocol to be used by both UserChoices class and UserChoicesMock for method injection
protocol UserChoicesPrivateUnitTesting {
static var choice1Method:(UIViewController) -> Void { get set }
static var choice2Method:(UIViewController) -> Void { get set }
}
// this popup that will be presented with a public method
public class ChoiceViewController:UIViewController {
@IBOutlet weak var titleLabel: UILabel!
@IBOutlet weak var subjectLabel: UILabel!
@IBOutlet weak var choice1Button: UIButton!
@IBOutlet weak var choice2Button: UIButton!
var choice1Action:(() -> Void)?
var choice2Action:(() -> Void)?
// ...
}
public class UserChoices: UIViewController, UserChoicesPrivateUnitTesting {
static var choice1Method: (UIViewController) -> Void = choice1
static var choice2Method: (UIViewController) -> Void = choice2
private static func choice1(onTopViewController: UIViewController) {
//present choice1Popup
}
private static func choice2(onTopViewController: UIViewController) {
//present choice2Popup
}
public static func presentChoiceViewController(onTopViewController: UIViewController, ChoiceViewController: ChoiceViewController = ChoiceViewController.instantiateFromAppStoryBoard(appStoryBoard: .MenuStoryboard)) {
let isCustomAnimated = true
// ChoiceViewController.transitioningDelegate = transitionDelegate
ChoiceViewController.choice1Action = { [weak onTopViewController]() in
guard let weakSelf = onTopViewController else {
return
}
weakSelf.dismiss(animated: false, completion: nil)
UserChoices.choice1Method(onTopViewController!)
}
ChoiceViewController.choice2Action = { [weak onTopViewController]() in
guard let weakSelf = onTopViewController else {
return
}
weakSelf.dismiss(animated: false, completion: nil)
UserChoices.choice2Method(onTopViewController!)
}
onTopViewController.present(ChoiceViewController, animated: isCustomAnimated, completion: nil)
}
}
import XCTest
@testable import ChoiceModule
public class UserChoicesMock:UserChoicesPrivateUnitTesting {
static public var choice1Method: (UIViewController) -> Void = choice1
static public var choice2Method: (UIViewController) -> Void = choice2
static var choice1MethodCalled = false
static var choice2MethodCalled = false
static func choice1(onTopViewController: UIViewController) {
choice1MethodCalled = true
}
static func choice2(onTopViewController: UIViewController) {
choice2MethodCalled = true
}
}
class UserChoicesTests: XCTestCase {
func testChoice1CallsPrivateChoice1Method() {
// This is an example of a functional test case.
let vc = UIViewController()
let choiceViewController = ChoiceViewController.instantiateFromAppStoryBoard(appStoryBoard: .MenuStoryboard)
UserChoices.choice1Method = UserChoicesMock.choice1Method
UserChoices.presentChoiceViewController(onTopViewController: vc, ChoiceViewController: choiceViewController)
choiceViewController.choice1Button.sendActions(for: .touchUpInside)
if UserChoicesMock.choice1MethodCalled == false {
XCTFail("choice1Method not called")
}
}
}
答案 0 :(得分:1)
测试无法访问声明为private
的任何内容。只要测试代码可以internal
,他们就可以访问声明为@testable import
的任何内容。
当您感到不安时,“但是我不必暴露这一点”,请考虑您的类实际上具有多个接口。这里有“它所做的一切接口”,还有“生产代码接口所需的零件”。有很多事情要考虑: