コールバックが正しいディスパッチキューで呼び出されるかどうかをテストするいくつかの単体テストがあります。
Swift 2で、現在のキューのラベルをテストキューと比較しました。ただし、Swift 3では、DISPATCH_CURRENT_QUEUE_LABEL
定数は存在しません。
dispatch_assert_queue
関数は見つかりました。それは私が必要とするもののようですが、それをどのように呼び出すかわかりません。
私のSwift 2コード:
let testQueueLabel = "com.example.my-test-queue"
let testQueue = dispatch_queue_create(testQueueLabel, nil)
let currentQueueLabel = String(UTF8String: dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL))!
XCTAssertEqual(currentQueueLabel, testQueueLabel, "callback should be called on specified queue")
更新:
オートコンプリートがないことで混乱しましたが、__dispatch_assert_queue
を使用することは可能です:
if #available(iOS 10.0, *) {
__dispatch_assert_queue(test1Queue)
}
これは単体テストでは機能しますが、テストが失敗するだけでなく、EXC_BAD_INSTRUCTION
でプロセス全体がうっとうしく停止します。
私自身の質問に答える:
KFDoomのコメント に基づいて、setSpecific
およびgetSpecific
を使用しています。
これにより、キーが作成され、テストキューに設定され、後で再び取得されます。
let testQueueLabel = "com.example.my-test-queue"
let testQueue = DispatchQueue(label: testQueueLabel, attributes: [])
let testQueueKey = DispatchSpecificKey<Void>()
testQueue.setSpecific(key: testQueueKey, value: ())
// ... later on, to test:
XCTAssertNotNil(DispatchQueue.getSpecific(key: testQueueKey), "callback should be called on specified queue")
キーに関連付けられている値がないことに注意してください(そのタイプはVoid
です)。私は特定の値の存在ではなく、特定の値の存在にのみ関心があります。
重要!
必ずキーへの参照を保持するか、使用後はクリーンアップしてください。そうしないと、新しく作成されたキーが同じメモリアドレスを使用し、奇妙な動作を引き起こす可能性があります。参照: http://tom.lokhorst.eu/2018/02/leaky-abstractions-in-Swift-with-dispatchqueue
dispatchPrecondition(.onQueue(expectedQueue))
を使用すると、Swift 3 APIの代わりにdispatch_assert_queue()
C APIを使用できます。
これは、今年のWWDC GCDセッションで取り上げられました: https://developer.Apple.com/videos/play/wwdc2016/720/
KFDoomの回答 に基づくテスト:
import XCTest
import Dispatch
class TestQueue: XCTestCase {
func testWithSpecificKey() {
let queue = DispatchQueue(label: "label")
let key = DispatchSpecificKey<Void>()
queue.setSpecific(key:key, value:())
let expectation1 = expectation(withDescription: "main")
let expectation2 = expectation(withDescription: "queue")
DispatchQueue.main.async {
if (DispatchQueue.getSpecific(key: key) == nil) {
expectation1.fulfill()
}
}
queue.async {
if (DispatchQueue.getSpecific(key: key) != nil) {
expectation2.fulfill()
}
}
waitForExpectations(withTimeout: 1, handler: nil)
}
func testWithPrecondition() {
let queue = DispatchQueue(label: "label")
let expectation1 = expectation(withDescription: "main")
let expectation2 = expectation(withDescription: "queue")
DispatchQueue.main.async {
dispatchPrecondition(condition: .notOnQueue(queue))
expectation1.fulfill()
}
queue.async {
dispatchPrecondition(condition: .onQueue(queue))
expectation2.fulfill()
}
waitForExpectations(withTimeout: 1, handler: nil)
}
}
1つのオプションは、キューを直接テストするための前提条件を設定するか、キューに「特定」を設定して後で取得することです。さらに、setSpecificとgetSpecificを使用できます。または、キューにいる場合は、前提条件チェックを使用して、「最新の取得」のニーズを満たす必要があります。 src: https://github.com/duemunk/Async/blob/feature/Swift_3.0/AsyncTest/AsyncTests.Swift
そして
https://github.com/Apple/Swift/blob/master/stdlib/public/SDK/Dispatch/Dispatch.Swift