为什么这个 Fixture 不止一次是 运行 它的构造函数?

Why this Fixture is running its constructor more than once?

为什么以下 xUnit 测试没有通过。 ProgramFixture 构造函数是 运行 3 次,但我只想为所有测试保留相同的实例,所以 Count 属性 应该是:1, 2, 3 in a序列。为什么它给我:1, 1, 1 因为它为每个 InlineData 测试实例化一个新的 ProgramFixture

节目:

namespace UnitTest
{
    public sealed class Program
    {
        public int Count { get; set; }

        public void IncrementCount()
        {
            ++this.Count;
        }

        // Mandatory Main method for the entry point.
        public static void Main() { }
    }
}

x单位:

using System;
using System.Diagnostics;
using Xunit;

namespace UnitTestTests
{
    public sealed class ProgramFixture : IDisposable
    {
        private bool disposed = false;

        public UnitTest.Program Program { get; }

        public ProgramFixture()
        {
            this.Program = new();
            Debug.WriteLine("################## ProgramFixture constructor runned.");
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        private void Dispose(bool disposing)
        {
            if (this.disposed)
                return;

            if (disposing)
            {
                Debug.WriteLine("################## ProgramFixture disposed.");
            }

            this.disposed = true;
        }
    }

    public sealed class UnitTest1 : IClassFixture<ProgramFixture>
    {
        private readonly ProgramFixture programFixture;

        public UnitTest1(ProgramFixture programFixture)
        {
            this.programFixture = programFixture;
        }

        [Theory]
        [InlineData(1)]
        [InlineData(2)]
        [InlineData(3)]
        public void Test1(int expectedCount)
        {
            this.programFixture.Program.IncrementCount();

            Assert.Equal(expectedCount, this.programFixture.Program.Count);
        }
    }
}

错误:

调试时:

我正在使用 Visual Studio Community 2019 16.10.3

这是 Visual Studio 上的错误还是某些机器特定的错误?

编辑

我的项目文件:

节目:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net5.0</TargetFramework>
  </PropertyGroup>

</Project>

x单位:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>net5.0</TargetFramework>

    <IsPackable>false</IsPackable>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.9.4" />
    <PackageReference Include="xunit" Version="2.4.1" />
    <PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
      <PrivateAssets>all</PrivateAssets>
    </PackageReference>
    <PackageReference Include="coverlet.collector" Version="3.0.2">
      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
      <PrivateAssets>all</PrivateAssets>
    </PackageReference>
  </ItemGroup>

  <ItemGroup>
    <ProjectReference Include="..\UnitTest\UnitTest.csproj" />
  </ItemGroup>

</Project>

编辑 2

我注意到我已经颠倒了其参数的 Assert.Equal 方法签名顺序,所以我将 Assert.Equal(this.programFixture.Program.Count, expectedCount) 编辑为 Assert.Equal(expectedCount, this.programFixture.Program.Count) 因此在第一个错误屏幕截图中显示的预期值和实际值右面板和这个不一样,问题还是一样

已确认错误并已在 https://github.com/xunit/xunit/issues 填写错误报告。不幸的是,我被迫使用一种不那么惯用的单元测试方法,但至少它是健壮的、可靠的,并且可以在没有 none 提到的问题的情况下工作,并且适合 Count 以外的另一个对象属性的目的在此单个测试上下文中保持其相同状态:

计划:

using System;
using System.Diagnostics;

namespace UnitTest
{
    public sealed class Program : IDisposable
    {
        public int Count { get; set; }

        private bool disposed = false;

        public Program()
        {
            Debug.WriteLine("################## Program constructor runned.");
        }

        public void IncrementCount()
        {
            ++this.Count;
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        private void Dispose(bool disposing)
        {
            if (this.disposed)
                return;

            if (disposing)
            {
                Debug.WriteLine("################## Program disposed.");
            }

            this.disposed = true;
        }

        // Mandatory Main method for the entry point.
        public static void Main() { }
    }
}

x单位:

using Xunit;

namespace UnitTestTests
{
    public sealed class UnitTest1
    {
        [Fact]
        public void Test1()
        {
            using (var program = new UnitTest.Program())
            {
                int[] expectedCounts = { 1, 2, 3 };

                foreach (var expectedCount in expectedCounts)
                {
                    program.IncrementCount();
                    Assert.Equal(expectedCount, program.Count);
                }
            }
        }
    }
}