为什么在测试时,NSTextView子类的undoManager总是为nil?
我有一个NSTextView的子类(MyTextView)。当我尝试用Swift测试它的 undoManager 属性时,它总是 nil,测试失败。
// Added extension
extension MyTextView {
override var undoManager: UndoManager? {
_testingUndoManager
}
}
@MainActor
struct Undo {
let mtv: MyTextView
init() throws {
mtv = MyTextView()
mtv.insertText("Lorem ipsum dolor sit amet")
mtv._testingUndoManager = UndoManager() // <-- Added
mtv.moveToBeginningOfDocument(self)
mtv.moveWordRightAndModifySelection(self)
}
@Test func roundtrip() async throws {
#expect(mtv.selections == [(0, 5)])
mtv.delete(self)
#expect(mtv.selections == [(0, 0)])
#expect(mtv.allowsUndo)
mtv.undoManager?.undo() // undoManager is always nil
#expect(mtv.selections == [(0, 5)])
let strings = mtv.getSelectedText()
#expect(strings == ["Lorem"])
}
}
显然测试并没有把完整的机制(运行循环?)设置好。有没有办法在测试期间强制实例化一个撤销管理器(undo manager)?
编辑: 我已经把上面的代码更新为到目前为止我找到的唯一解决方案,以防将来遇到同样情况的朋友。不幸的是,这需要在 NSTextView 子类中添加一个实例变量:
var _testingUndoManager: UndoManager? = nil
解决方案
你所看到的问题是AppKit的预期行为,NSUndoManager 的 NSTextView 只有在视图在真实的 NSWindow 中创建时才会被创建。在单元测试场景中,视图仅存在于内存中,测试用例中不存在 NSWindow,因此没有响应者链,导致undoManager返回nil。一个解决方案就是你已经在做的那个,另一种解决方案是通过编程方式创建 NSWindow 并将其附加到你的 NSView。
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。