2016-12-23 9 views
1

最近、私が書いたオブジェクトが単体テストを使って適切に割り当て解除されたことを確認しようとしていました。私は、テストが完了する前に、オブジェクトを試しても、割り当てを解除していなかったことに気がつきました。そこで私は、弱い変数を使ってオブジェクトの割り振りの基礎を証明しようとする簡単な例(下記参照)にテストを縮小しました。Swift XCTest:弱い変数の適切な割り当て解除を確認する

私の考えでは、強力なリファレンスはテストメソッドが終了した後にオブジェクトを保持しなくてはならず、弱いリファレンスは次の実行ループで参照されるときはnilでなければなりません。しかし、弱参照は決してゼロではなく、両方のテストは失敗します。私はここで何か誤解していますか?以下は完全な単体テストです。

class Mock { //class type, should behave with reference semantics 

    init() { } 
} 

class DeallocationTests: XCTestCase { 

    func testWeakVarDeallocation() { 

     let strongMock = Mock() 

     weak var weakMock: Mock? = strongMock 

     let expt = expectation(description: "deallocated") 

     DispatchQueue.main.async { 

      XCTAssertNil(weakMock)  //This assertion fails 

      expt.fulfill() 
     } 

     waitForExpectations(timeout: 1.0, handler: nil) 
    } 

    func testCaptureListDeallocation() { 

     let strongMock = Mock() 

     let expt = expectation(description: "deallocated") 

     DispatchQueue.main.async { [weak weakMock = strongMock] in 

      XCTAssertNil(weakMock)  //This assertion also fails 

      expt.fulfill() 
     } 

     waitForExpectations(timeout: 1.0, handler: nil) 
    } 
} 

私は多分解除がXCTestで何とか延期されていたと思ったが、それでもautoreleasepoolのテストメソッド本体をラッピングすると、オブジェクトが割り当て解除されることはありませんでした。

+0

'例えば、オプションにする必要がありweakMock'弱い弱い弱いモック:モック? = strongMock'。 'nil'に設定できない場合は解放できません。 – par

+0

@par 'weakMock'は自動的にオプションで、コンパイラによって強制されます。 'weakMock'の型を調べると、明示的な型の注釈なしで' Mock? 'になっています。 –

+0

明示的にオプションにすると、それはゼロになりますか? – par

答えて

3

strongMockへの強い参照がまだ保持されているので、dispatchAsyncブロックが呼び出されたときにtestWeakVarDeallocation()関数が終了しないという問題があります。

testWeakVarDeallocation()が出ることを可能に)このようにそれを試してみて、あなたが期待通りweakMocknilなっわかります

class weakTestTests: XCTestCase { 
    var strongMock: Mock? = Mock() 

    func testWeakVarDeallocation() { 
     weak var weakMock = strongMock 

     print("weakMock is \(weakMock)") 

     let expt = self.expectation(description: "deallocated") 

     strongMock = nil 

     print("weakMock is now \(weakMock)") 

     DispatchQueue.main.async { 
      XCTAssertNil(weakMock)  // This assertion fails 

      print("fulfilling expectation") 
      expt.fulfill() 
     } 

     print("waiting for expectation") 
     self.waitForExpectations(timeout: 1.0, handler: nil) 
     print("expectation fulfilled") 
    } 
} 
+0

オブジェクトが割り当てを解除しない理由は正しいですが、解決策では問題が解決されません。待機する予定がないため、最初の非同期ブロックが実行される前にテストが完了してパスします。かなりキャッチ22。 –

+0

あなたはそうです、XCTest関数は待っていません。私は答えを更新しました、そして今、正しいことをします。 – par

+0

うん、それは、私はautoreleasepoolを使用して、以下の問題を考え出したが、あなたのソリューションは本質的に同じです。助けてくれてありがとう! –

関連する問題