c# - 我在结合 dotMemory、xUnit 和 async 时做错了什么吗

标签 c# async-await xunit dotmemory

我有一个单元测试,我试图验证我已经处理了曾经附加到主用户界面的文档。单元测试必须是异步的,因为所有内容都需要在 STA 线程下运行,我必须等待创建用户界面。

我有一个助手可以将操作分派(dispatch)到 STA 线程。

我在测试的主体中创建了 memory 对象,然后将其传递给异步方法,如下所示。

查看用 ### 注释的代码行以查看实际的问题行。 dotMemory 报告该对象尚不存在,但我已经断言证明该对象确实存在。

(STA Helper 类可以在 https://gist.github.com/bradphelan/cb4f484fbf6a7f9829de0dd52036fd63 找到)

这是与 async 和 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 失败,sync 通过。

[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);
    }
}

最佳答案

对我来说,将测试包装在本地函数中就足够了:

public void TestMethod()
{
    async Task LocalFunction()
    {
        // here you can make async calls
        await Task.Delay(...);
    }

    LocalFunction().ConfigureAwait(true).GetAwaiter().GetResult();
}

关于c# - 我在结合 dotMemory、xUnit 和 async 时做错了什么吗,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40968613/

相关文章:

c# - 使用 Documentformat.OpenXML 在 C# 中验证 Excel 文件

c# - 不需要等待的异步任务方法

javascript - 捕获地理位置错误 - 异步等待

c# - xunit 是否有参数化测试夹具?

c# - 没有泛型的测试类简化

Javascript,Ember 2,如何重构此 promise 代码(也许还可以使用 async/await)

c# - 如果启动太多线程会怎样?

c# - 传递 javascript 参数并在 unity C# 文件中使用它们

c# - ReadOnlyDictionary 和 ImmutableDictionary 有什么区别?

c# - write() 和 memcpy() 在字节大小方面的区别