2016-12-05 62 views
4

我有一個單元測試,我試圖驗證我已經處理過一次附加到主用戶界面的文檔。單元測試必須是異步的,因爲一切都需要在STA線程下運行,我必須等待創建的用戶界面。我做錯了什麼結合dotMemory,xUnit和異步

我有一個幫助器,將操作分派到STA線程。

我在測試的主體中創建了內存對象,然後將其傳遞給下面的異步方法。

查看用評論的代碼行###查看實際問題行。 dotMemory報告該對象不存在,但我已經做出了證明對象確實存在的斷言。

(STA Helper類可以在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); 
    } 
} 

我已經創建了同樣的上述測試的同步版本,它不會失敗。有兩個測試ShouldCollectAsyncShouldCollectSyncasync one failed and sync one pass。

[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調用,但dotMemory告訴我,我試圖運行並行測試。 – bradgonesurfing

+0

獲取對象是否運行異步? –

+0

不,它不。 – bradgonesurfing

回答

1

dotMemory Unit要求所有的方法應該從「test」方法中調用。 想想就好像有一個叫dotMemoryUnit.TestStart的 ShouldCollectAsync和dotMemoryUnit.TestEnd開頭。 您沒有公開實現STAThread.Run,​​所以我不能給出更詳細的建議,但是想法是在異步例程完成時等待測試方法。

+0

我自己也會得出同樣的結論。 – bradgonesurfing