如何测试没有数据写入 NSPipe

How to test that no data is written to an NSPipe

我最近一直在研究日志框架,如果用户不希望日志消息消失,我允许用户提供 NSPipe 来关闭日志到控制台。

Logger 可以启用或禁用,禁用时不应向管道发送任何数据。

启用记录器后,很容易检查数据是否已通过管道发送,因为 availableData 立即包含数据,并触发 NSFileHandleDataAvailableNotification/readabilityHandler 块。

但是,如果您要测试数据未通过管道发送,并尝试应用 availableData 不包含任何数据的相同想法,则测试将仅在 availableData 时超时returns 一旦收到数据。

我想出了一个解决方案,那就是监听通知,如果在 X 秒后还没有收到通知,则满足没有收到通知的期望,前提是如果收到通知,期望将实现两次(导致测试失败)。

这种方法的问题是,如果由于某种原因,管道确实收到了一些数据,一旦在 readabilityHandler 块中满足期望,测试立即成功,并且没有满足期望第二次:

func testDisabledLoggerDoesntLog() {
    let logger = Logger()
    let pipe = NSPipe()

    logger.pipe = pipe
    logger.enabled = false

    let expectation = expectationWithDescription("handler not triggered")
    logger.pipe!.fileHandleForReading.readabilityHandler = { handler in
        expectation.fulfill()
    }

    logger.debug("Test message")

    fulfillAfter(expectation, time: 2)

    waitForExpectationsWithTimeout(3, handler: nil)
}

func fulfillAfter(expectation: XCTestExpectation, time: Double = 4) {
    let delayTime = dispatch_time(DISPATCH_TIME_NOW, Int64(time * Double(NSEC_PER_SEC)))
    dispatch_after(delayTime, dispatch_get_main_queue()) {
        expectation.fulfill()
    }
}

有什么更好的方法可以在管道接收到数据时导致测试失败,而在没有接收到数据时导致测试通过?

如评论中所述,我找到了一个单独的解决方案,它将任意数据写入管道,执行日志(这可能会或可能不会导致将更多数据写入管道),然后检索来自管道 availableData.

的数据

如果availableData的长度等于任意数据的长度,那么很明显日志还没有写入管道。否则如果长度大于测试写入的数据,则日志确实已经执行并将其数据写入管道。

let logger = Logger()
let pipe = NSPipe()

logger.pipe = pipe
logger.enabled = false
logger.useCurrentThread = true // The logs generally use a background thread to prevent interrupting the main queue. In this test, the current thread must be used in order for it to be synchronous.

let writtenData = "written data".dataUsingEncoding(NSUTF8StringEncoding)!
logger.pipe!.fileHandleForWriting.writeData(writtenData)

logger.debug("Test message")

XCTAssertEqual(logger.pipe!.fileHandleForReading.availableData.length, writtenData.length)