我有一个viewcontroller类,它显示一系列两种选择的弹出视图。每两个选项弹出视图都是不同的。
弹出1-选项1->选项1弹出
弹出1-选项2-选项2弹出
我打算将popup1呈现为公共的方法,但我希望呈现choice1popup和choice2popup的其他方法是私有的。
如果我决定要测试选项1选项和选项2选项,那么我可能需要将它们设置为内部而不是私有,但它们不太可能在其他地方使用。
我想编写一个单元测试,测试当触摸choice1的按钮时,是否调用表示choice1popup的方法。我使用了一个带有方法类型变量的协议来允许模拟注入弹出式展示器的模拟版本。我对自己的方法不太满意,所以我想知道是否有更好的方法。
顺便说一下,我对内部和私人之间的冲突感到很矛盾。能够测试我的私有方法是很好的,但是我不希望它们能够从任何地方被调用,除了单元测试,并且使它们内部公开。
下面是代码,下面是单个单元测试:
protocol UserChoicesPrivateUnitTesting {
static var choice1Method:(UIViewController) -> Void { get set }
static var choice2Method:(UIViewController) -> Void { get set }
}
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) {
}
private static func choice2(onTopViewController: UIViewController) {
}
public static func presentChoiceViewController(onTopViewController: UIViewController, ChoiceViewController: ChoiceViewController = ChoiceViewController.instantiateFromAppStoryBoard(appStoryBoard: .MenuStoryboard)) {
let isCustomAnimated = true
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() {
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")
}
}
}