这是我的单元测试:
func testDeinit() {
let view = DocumentsView(theme: MockTheme())
let viewModel = DocumentsViewModelMock()
let delegate = DocumentsViewControllerDelegateMock()
var controller: DocumentsViewController? = DocumentsViewController(view: view, viewModel: viewModel, delegate: delegate)
controller?.viewDidLoad()
let expectation = self.expectation(description: "")
XCTAssertFalse(delegate.documentViewControllerDeinitializedWasCalled)
controller = nil
XCTAssertTrue(delegate.documentViewControllerDeinitializedWasCalled)
}
deinit
看起来像这样:
deinit {
delegate?.documentViewControllerDeinitialized()
}
和我的代表:
class DocumentsViewControllerDelegateMock: DocumentsViewControllerDelegate {
var documentViewControllerDeinitializedWasCalled = false
func documentViewControllerDeinitialized() {
documentViewControllerDeinitializedWasCalled = true
}
}
我对DocumentsViewController
的初始化。
private weak var delegate: DocumentsViewControllerDelegate?
// MARK: - Initialization
init(view: DocumentsView, viewModel: DocumentsViewModelable, delegate: DocumentsViewControllerDelegate) {
self.mainView = view
self.viewModel = viewModel
self.delegate = delegate
super.init(nibName: nil, bundle: nil)
}
上面的单元测试失败。为什么?
这种情况是因为检查了deinit的名称为 AFTER 。异步方式怎么做?
答案 0 :(得分:1)
恕我直言,这是一个糟糕的测试。
您基本上是在测试如果对象已释放,则deinit
中的内容是否被调用。那不是您要测试的东西。苹果的Swift设计师应该对此进行测试。
请另外做两个测试。
controller = nil
之后是否已释放控制器。您可以只执行XCTAssertNil
。诀窍是获取对控制器的weak
引用,以便将其传递给assert deinit
方法内部的内容。在
您的情况将是手动触发
delegate?.documentViewControllerDeinitialized()
+
XCTAssertTrue(delegate.documentViewControllerDeinitializedWasCalled)
通过这种方式,您还可以避免嘲笑DocumentsViewControllerDelegate
协议。
答案 1 :(得分:0)
在初始化delegate
之后,单元测试中的DocumentsViewController
很可能会立即解除分配。这是因为此后不再有对委托的更强引用,控制器中只有weak
个引用。因此,控制器不再具有委托来调用deinit。
尝试延长代表的寿命,例如通过对其进行虚拟断言(例如XCTAssertEquals(controller.delegate, delegate)
。
答案 2 :(得分:-2)
您真的需要使用deinit方法吗?
在实例解除分配发生之前,会自动调用反初始化器。您不允许自己调用反初始化器。超类反初始化器由其子类继承,并且超类反初始化器在子类反初始化器实现的末尾自动调用。即使子类不提供自己的反初始化器,也总是调用超类反初始化器。
Blockquotee因为在取消调用实例之前,实例不会被释放,所以取消初始化程序可以访问其实例的所有属性,并可以基于这些属性修改其行为(例如查找所需文件的名称)关闭)。
来自https://docs.swift.org/swift-book/LanguageGuide/Deinitialization.html