我将dotMemory,xUnit和async结合起来做错了吗 [英] Am I doing something wrong combining dotMemory, xUnit and async
问题描述
我有一个单元测试,在该测试中,我试图验证是否已处置了曾经附加到主用户界面的文档.单元测试必须是异步的,因为一切都需要在STA线程下运行,而我必须等待正在创建的用户界面.
I have a unit test where I try to verify that I have disposed of a document that was once attached to the main user interface. The unit test has to be async in that everything needs to be run under an STA thread and I have to await the user interface being created.
我有一个助手,可以将操作分派到STA线程上.
I have a helper that dispatches actions onto an STA thread.
我在测试的主体中创建内存对象,然后将其传递给异步方法,如下所示.
I create the memory object in the main body of the test and then pass it to the async methods as below.
查看用 ### 注释的代码行,以查看实际的问题行. dotMemory报告该对象尚不存在,但我已经断言该对象确实存在.
See the lines of code commented with ### to see the actual problem line. dotMemory is reporting that the object does not yet exist but I have already made an assertion proving that the object does exist.
(STA Helper类可以在 https://gist.github.com/bradphelan/cb4f484fbf6a7f9829de0dd中找到)
( STA Helper classes can be found at https://gist.github.com/bradphelan/cb4f484fbf6a7f9829de0dd52036fd63 )
这与async和dotMemory有关吗?
Is this a problem to do with async and 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);
}
}
我已经创建了与上述测试相同的同步版本,并且没有失败. ShouldCollectAsync 和 ShouldCollectSync 下面有两个测试. 异步一项失败,同步一项通过.
I have created a synchronous version of the same above test and it doesn't fail. There are two tests below ShouldCollectAsync and ShouldCollectSync. The async one fails and the sync one passes.
[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);
}
}
推荐答案
dotMemory单元要求其所有方法都应从"test"方法中调用. 考虑一下,就像在开始时就调用了dotMemoryUnit.TestStart一样. 在完成后,ShouldCollectAsync和dotMemoryUnit.TestEnd. 您没有公开STAThread.Run的实现,因此我无法提供更详细的建议,但其想法是在异步例程完成后等待测试方法.
dotMemory Unit requires that all its method should be called from the "test" method. Think about that like there is a call dotMemoryUnit.TestStart at the very begin of ShouldCollectAsync and dotMemoryUnit.TestEnd on finish. You did not expose implementation of STAThread.Run, so I can't give more detailed advise, but the idea is to wait in the test method while you async routine is finished.
这篇关于我将dotMemory,xUnit和async结合起来做错了吗的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!