【问题标题】:How to test required init(coder:)?如何测试所需的 init(coder:)?
【发布时间】:2015-12-06 15:23:12
【问题描述】:

在我的自定义类 WLNetworkClient 中,我必须实现这样的方法:

required init(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}

我不需要使用它,但我想测试它以实现 100% 的代码覆盖率。你知道如何实现吗?

我尝试了以下方法但没有成功:

let nc = WLNetworkClient(coder: NSCoder())
XCTAssertNotNil(nc)

【问题讨论】:

    标签: swift unit-testing xcode7.1beta


    【解决方案1】:

    Here 是对你有帮助的答案:

    let cd = NSKeyedUnarchiver(forReadingWithData: NSMutableData())
    let c = CustomTextField(coder:cd)
    

    【讨论】:

    • 不幸的是它仍然不起作用:*** -[NSKeyedUnarchiver initForReadingWithData:]: data is empty; did you forget to send -finishEncoding to the NSKeyedArchiver?
    【解决方案2】:

    生产代码:

    required init?(coder: NSCoder) {
        return nil
    }
    

    测试:

    func testInitWithCoder() {
        let archiverData = NSMutableData()
        let archiver = NSKeyedArchiver(forWritingWithMutableData: archiverData)
        let someView = SomeView(coder: archiver)
        XCTAssertNil(someView)
    }
    

    由于所需的初始化器返回nil并且不使用编码器,所以上面的代码可以简化为:

    func testInitWithCoder() {
        let someView = SomeView(coder: NSCoder())
        XCTAssertNil(someView)
    }
    

    【讨论】:

    • 这在稍微不同的情况下对我不起作用。我将 super.init(coder: aDecoder) 称为第二行,它停止在该行上运行。没有崩溃只是没有完成测试。
    • 对我来说失败了(Xcode 9.3,Swift 4.1):test failure: testInitWithCoder() failed: failed: caught "NSInvalidArgumentException", "*** -decodeObjectForKey: only defined for abstract class. Define -[NSKeyedArchiver decodeObjectForKey:]!"
    • @Oliver,当我收到该错误时,这是​​因为我正在为我的初始化程序提供一个专用的存档器而不是专用的 DEarchiver ...我应该创建一个新的 NSKeyedUnarchiver,并将 archiverData 作为 init 参数.
    • 初始化器 NSKeyedArchiver(forWritingWith:) 在 iOS12 中已被弃用。如果您收到该警告,可以将该行替换为 let archiver = NSKeyedArchiver(requiringSecureCoding: true)
    • 这现在不起作用,失败并出现错误caught "NSInvalidArgumentException", "*** -containsValueForKey: cannot be sent to an abstract object of class NSCoder: Create a concrete instance!"
    【解决方案3】:

    Rudolf Adamkovič 的回答仍在使用 Swift 4:

    required init?(coder aDecoder: NSCoder) {
        return nil
    }
    
    func testInitWithCoder() {
        // 1. Arrange
        let archiver = NSKeyedArchiver(forWritingWith: NSMutableData())
    
        // 2. Action
        let viewController = ViewController(coder: archiver)
    
        // 3. Assert
        XCTAssertNil(viewController)
    }
    

    【讨论】:

    • XCTAssertNil? XCTAssertNotNil 当然。
    • @Oliver Pearmain 鉴于当前的实现返回 nil,AssertNil 是正确的测试(即使我们大多数人可能会有 NotNil)
    • NSKeyedArchiver(forWritingWith: NSMutableData()) 已弃用。
    【解决方案4】:

    我将 Rudolf 的回答与 Liz 的建议结合起来,以以下解决方案结束:

    let viewController = SomeTableViewController(
        presenter: SomePresenterMock(),
        coder: NSKeyedUnarchiver(forReadingWith: Data())) 
    
    XCTAssert(viewController?.tableView.numberOfSections == 1)
    

    这里的关键是使用NSKeyedUnarchiver(forReadingWith: Data())作为模拟编码器,否则测试会因NSInvalidArgumentException而崩溃。

    【讨论】:

      【解决方案5】:

      我使用改进的 Rudolf 的 Adamkovič 答案:

      required init?(coder aDecoder: NSCoder) {
          super.init(coder: aDecoder)
      }
      
      func test_initWithCoder() {
          let object = SomeView()
          let data = NSKeyedArchiver.archivedData(withRootObject: object)
          let coder = NSKeyedUnarchiver(forReadingWith: data)
          let sut = SomeView(coder: coder)
          XCTAssertNotNil(sut)
      }
      

      【讨论】:

        【解决方案6】:

        似乎所有以前的答案在 Swift 5 之后都停止工作了。

        我设法修改了@ChikabuZ 答案并使它像这样工作:

        func testInitWithCoder() {
            // Given
            let object = SomeView()
            let data = try! NSKeyedArchiver.archivedData(withRootObject: object, requiringSecureCoding: false)
            let coder = try! NSKeyedUnarchiver(forReadingFrom: data)
        
            // When
            let sut = SomeView(coder: coder)
        
            // Then
            XCTAssertNotNil(sut)
        }
        

        【讨论】:

          猜你喜欢
          • 2014-12-07
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-05-17
          • 2016-11-18
          • 1970-01-01
          相关资源
          最近更新 更多