2016-12-05 3 views
4

私は一度メインのユーザーインターフェイスに添付された文書を廃棄したことを確認しようとするユニットテストをしています。単体テストは、すべてがSTAスレッドの下で実行される必要があるという点で非同期でなければならず、作成されるユーザーインターフェイスを待たなければなりません。dotMemory、xUnit、asyncを組み合わせて間違ったことをしていますか?

私は、STAスレッドにアクションをディスパッチするヘルパーを持っています。

私はメモリオブジェクトをテスト本体に作成し、それを以下のように非同期メソッドに渡します。

実際の問題行を表示するには、###とコメントされたコード行を参照してください。 dotMemoryはオブジェクトがまだ存在しないと報告していますが、オブジェクトが存在することを証明するアサーションをすでに作成しています。

(STAヘルパークラスはhttps://gist.github.com/bradphelan/cb4f484fbf6a7f9829de0dd52036fd63で見つけることができます)

が、これは非同期とdotMemoryを行うには問題ですか?

[Collection("Memory leaks")] 
public class MemLeakSpec 
{ 
    public MemLeakSpec(ITestOutputHelper output) 
    { 
     DotMemoryUnitTestOutput.SetOutputMethod(output.WriteLine); 
    } 

    [Fact] 
    [DotMemoryUnit(FailIfRunWithoutSupport = true)] 
    public void ShouldCollectProjectX() 
    { 
     dotMemory.Check (memory => { STAThread.Run(() => ShouldCollectProjectAsyncX(memory)).Wait(); }); 
    } 

    class Document { } 

    class Container { public Document Document; }; 

    Document CreateFoo() => new Document(); 

    private async Task ShouldCollectProjectAsyncX(Memory memory) 
    { 
     await Task.Delay(TimeSpan.FromMilliseconds(50)); 

     Container container = new Container(); 

     memory.GetObjects(@where => @where.Type.Is<Document>()) 
         .ObjectsCount.Should() 
         .Be(0); 

     Document documentA = CreateFoo(); 
     container.Document = documentA; 

     // Verify with dotMemory that the object exists. 
     // ### This fails even though I have verified 
     // ### the document exists 
     memory.GetObjects(@where => @where.Type.Is<Document>()) 
         .ObjectsCount.Should() 
         .Be(1); 

     // Open a new project which should dispose the old one and thus 
     // remove any reference to GenericWeinCadFolder 
     container.Document = null; 

     memory.GetObjects(@where => @where.Type.Is<Document>()) 
         .ObjectsCount.Should() 
         .Be(0); 


     GC.KeepAlive(container); 
    } 
} 

上記の同じテストの同期バージョンが作成されており、失敗しません。以下の2つのテストがあります。ShouldCollectAsyncおよびShouldCollectSync非同期が失敗し、を1つ通過します。

[Collection("Memory leaks")] 
public class MemLeakSpec 
{ 
    public MemLeakSpec(ITestOutputHelper output) 
    { 
     DotMemoryUnitTestOutput.SetOutputMethod(output.WriteLine); 
    } 

    [Fact] 
    [DotMemoryUnit(FailIfRunWithoutSupport = true)] 
    public void ShouldCollectAsync() 
    { 
     dotMemory.Check (memory => { STAThread.Run(() => ShouldCollectProjectAsyncX(memory)).Wait(); }); 
    } 

    /// This test is almost identical to the ShouldCollectAsync 
    /// but it passes 
    [Fact] 
    [DotMemoryUnit(FailIfRunWithoutSupport = true)] 
    public void ShouldCollectSync() 
    { 
     dotMemory.Check (memory => { STAThread.Run(() => ShouldCollectProjectSync(memory)); }); 
    } 

    class Document { } 

    class Container { public Document Document; }; 

    Document CreateFoo() => new Document(); 

    private async Task ShouldCollectProjectSync(Memory memory) 
    { 
     Container container = new Container(); 

     memory.GetObjects(@where => @where.Type.Is<Document>()) 
         .ObjectsCount.Should() 
         .Be(0); 

     Document documentA = CreateFoo(); 
     container.Document = documentA; 

     // Verify with dotMemory that the object exists. 
     // #### Passes here 
     memory.GetObjects(@where => @where.Type.Is<Document>()) 
         .ObjectsCount.Should() 
         .Be(1); 

     GC.KeepAlive(documentA); 
     GC.KeepAlive(container); 
    } 
    private async Task ShouldCollectProjectAsyncX(Memory memory) 
    { 

     await Task.Delay(TimeSpan.FromMilliseconds(50)); 

     Container container = new Container(); 

     memory.GetObjects(@where => @where.Type.Is<Document>()) 
         .ObjectsCount.Should() 
         .Be(0); 

     Document documentA = CreateFoo(); 
     container.Document = documentA; 

     // Verify with dotMemory that the object exists. 
     // #### FAILS here 
     memory.GetObjects(@where => @where.Type.Is<Document>()) 
         .ObjectsCount.Should() 
         .Be(1); 

     GC.KeepAlive(documentA); 
     GC.KeepAlive(container); 
    } 
} 
+0

私は、非同期メソッド内にdotMemory.Check呼び出しを入れようとしましたが、並列テストを実行しようとしています。 – bradgonesurfing

+0

オブジェクトは非同期で実行されますか? –

+0

いいえ、そうではありません。 – bradgonesurfing

答えて

1

dotMemoryユニットでは、すべてのメソッドを「テスト」メソッドから呼び出す必要があります。 終了時に ShouldCollectAsyncとdotMemoryUnit.TestEndの先頭にdotMemoryUnit.TestStartという呼び出しがあるように考えてみましょう。 あなたはSTAThread.Runの実装を公開していませんでしたので、より詳細なアドバイスはできませんが、非同期ルーチンが終了している間はテストメソッドを待つことです。

+0

私はちょうど同じ結論になりました。 – bradgonesurfing

関連する問題