4

iOSの - 次のように私がテストしようとしている方法の一部であるユニットテストAsynchoronousコード

- (void)configureTableFooterView { 
    dispatch_async(dispatch_get_main_queue(), ^{ 
     self.tableView.tableFooterView = nil; 

     if ([self.parser.resultSet isLastPage]) { 
      return; 
     } 
    }); 
} 

次のように私はユニットテストを書かれている:

- (void)testTableFooterViewConfigurationAfterLastPageLoaded { 

    id mockTableView = OCMClassMock([GMGFlatTableView class]); 

    OCMExpect([mockTableView setTableFooterView:[OCMArg isNil]]); 

    id resultSet = OCMClassMock([GMGResultSetInfo class]); 

    OCMStub([resultSet isLastPage]).andReturn(YES); 

    OCMStub([self.mockParser resultSet]).andReturn(resultSet); 

    id partialMockSUT = OCMPartialMock(self.sut); 

    OCMStub([partialMockSUT tableView]).andReturn(mockTableView); 

    [self.sut configureTableFooterView]; 

    OCMVerifyAllWithDelay(mockTableView, 2.0); 

    //OCMVerifyAllWithDelay(partialMockSUT, 2.0); 
} 

私は別のものを持っていますメインスレッドのdispatch_async呼び出しと同じものをテストしている同じクラスでテストしてください。そのテストでのテストの期待値と検証設定はこれと一致します。そのテストに合格すると、遅延検証ステップで無限ループに陥ることになります。

興味深いことに、私はこの1回のテストを実行するだけで問題は解決します。このテストが他のテストで実行されている場合にのみ、その問題が表示されます。

UPDATE:

In unit test, execute the block passed in queue with dispatch_asyc

これは、はるかに関連する記事です。しかし、これは本来の試験方法とまったく同じ方法でほとんど失敗:

- (void)testTableFooterViewConfigurationAfterLastPageLoaded { 

    id mockTableView = OCMClassMock([GMGFlatTableView class]); 

    OCMExpect([mockTableView setTableFooterView:[OCMArg isNil]]); 

    id resultSet = OCMClassMock([GMGResultSetInfo class]); 

    OCMStub([resultSet isLastPage]).andReturn(YES); 

    OCMStub([self.mockParser resultSet]).andReturn(resultSet); 

    id partialMockSUT = OCMPartialMock(self.sut); 

    OCMStub([partialMockSUT tableView]).andReturn(mockTableView); 

    [self.sut configureTableFooterView]; 

    [[NSRunLoop mainRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.01]]; 

    OCMVerifyAll(mockTableView); 
} 

NSRunLoopを持つ行がスイートとして実行したときにEXC_BAD_ACCESSでクラッシュそれだけで正常に動作します!

+0

http://stackoverflow.com/questions/18667355/how-to-test-async-method-in-block-using-ocmockをチェックしましたか? – jcaron

+0

これはUIテストには適していることに注意してください。単位テストではありません。 – Cristik

+0

@Cristik私は理解していますが、テスト中のメソッドはかなりスタンドアロンであり、単体テストを使って正しく動作するかどうかを確認します。 UIテストは、メソッドがUIフローで正しく呼び出されることを確認します。しかし、問題は一般的にGCDに一般化できるので、私の質問は –

答えて

1

クラスラッパーをdispatch_asyncの周りに作成し、それを依存関係として渡すことができます。また、偽のラッパーを作成し、テストで渡すこともできます。あなたが興味を持っているなら、私ははるかに詳細な説明を提供することができます。

+0

dispatch_async C関数の回りにラッパークラスを書くのですか?もしそうなら、私はその考えが本当に好きではありません。また、私自身のテストを実行している限り、現在のテスト構成は実際に動作しています。それは私がすべてのテストを一緒に実行して失敗するときだけです。私はそれがどのように動作しているかの私の理解にいくつか不足しています –

+0

あなたのコードは単体テストではありません。依存関係のあるコードをテストすると機能テストと呼ばれ、他のテストではテストが失敗する理由を実際には分かりませんが、一般的には機能テストが原因です。 –

+0

これはまた、テーブルビューを管理しているクラスがディスパッチキューと非同期コードの実行を知っているため、単一責任の原則に違反します。 –

関連する問題