1

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

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

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

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

我想出了一个解决方案,那就是监听通知,如果 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()
    }
}

如果管道接收到数据,将导致测试失败,如果没有,则通过测试,更好的方法是什么?

4

1 回答 1

0

正如评论中所述,我找到了一个单独的解决方案,它将任意数据写入管道,执行日志(这可能会或可能不会导致更多数据写入管道),然后从管道的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)
于 2016-07-03T14:30:25.767 回答