Я разрабатываю приложение для macOS, используя swift.В моем приложении есть объект Alarm, который можно включить или отключить.Я создал привязку Какао из свойства enable будильника к флажку в пользовательском интерфейсе.Чтобы проверить, работает ли привязка, я добавил оператор print в метод наблюдателя свойства didSet состояния включенного Alarm, и это сообщение распечатывается при переключении флажка.
Теперь я хочу написать модульный тест дляубедитесь, что при переключении свойства enabled действительно выполняются правильные действия, и у меня возникают трудности с программным созданием привязки в модульном тесте, которая будет имитировать то, что происходит с привязкой, созданной в Interface Builder.
Тест выглядит как-токак это:
func testAlarmTogglesEnabledState() {
let alarm = Alarm()
let enabler = AlarmEnabler(alarm)
enabler.enable()
XCTAssertTrue(alarm.enabled)
}
Тест на самом деле более сложный, чем этот, так как аварийный сигнал на самом деле предпринимает некоторые действия, чтобы включить или отключить сам себя, однако, это, мы надеемся, служит в основном для иллюстрации того, что происходит.
Класс AlarmEnabled выглядит следующим образом:
@objc private class AlarmEnabler: NSObject {
init(_ alarm: Alarm) {
super.init()
let name = NSBindingName(rawValue: "enabled")
bind(name, to: alarm, withKeyPath: "enabled", options: nil)
}
func enable() {
enabled = true
}
@objc dynamic var enabled = false
}
И класс Alarm имеет такую форму:
@objc class Alarm: NSObject {
…
@objc private(set) var enabled = true {
didSet {
print("Alarm's enabled state was set to \(enabled)")
}
}
…
}
Сообщение в наблюдателе свойства didSet никогда не печатается при запуске теста, так что программная привязка явно не работает.
Вот игровая площадка, которую я пытался написать, которая в основном выполняет то, что пытается выполнить модульный тест:
import Cocoa
@objc class Alarm: NSObject, Codable {
init(_ enabled: Bool = true) {
self.enabled = enabled
}
@objc dynamic var enabled: Bool {
didSet {
print("Alarm's enabled state was set to \(enabled)")
}
}
}
@objc class AlarmEnabler: NSObject {
init(_ alarm: Alarm) {
self.alarm = alarm
super.init()
let name = NSBindingName(rawValue: #keyPath(AlarmEnabler.enabled))
bind(name, to: alarm, withKeyPath: #keyPath(Alarm.enabled), options: nil)
// bind(name, to: alarm, withKeyPath: #keyPath(AlarmEnabler.enabled), options: nil)
checkBox.bind(NSBindingName.value, to: alarm, withKeyPath: #keyPath(Alarm.enabled), options: nil)
}
deinit {
}
func enable() {
enabled = true
checkBox.state = .on
}
func disable() {
enabled = false
checkBox.state = .off
}
@objc func checkBoxToggled(_ sender: NSButton) {
}
let checkBox = NSButton(checkboxWithTitle: "", target: self, action: #selector(AlarmEnabler.checkBoxToggled))
@objc dynamic var enabled = false
let alarm: Alarm
}
let alarm = Alarm(false)
let enabler = AlarmEnabler(alarm)
enabler.enable()
enabler.disable()
Она правильно связывает сигнал тревоги, а также пытается имитировать то, что происходит в пользовательском интерфейсе,используя флажок.Кажется, что ни один из них не может заставить собственность измениться.Что может заставить код игровой площадки работать правильно?