【发布时间】:2018-08-17 11:37:17
【问题描述】:
我们设置了以下测试。
Permutations.Tests.fsproj
<ItemGroup>
<Compile Include="Permute1Tests.fs" />
<Compile Include="Permute2Tests.fs" />
</ItemGroup>
Permute1Tests.fs
module Permute1Tests
open Xunit
open Permutations.Permute1
[<Theory>]
[<MemberData("permuteTestValues")>]
let ``permute`` (x, expected) =
let actual = permute x
Assert.Equal<List<int>>(expected, actual);
let permuteTestValues : obj array seq =
seq {
yield [| [0;1]; [[0;1]; [1;0]] |]
}
Permute2Tests.fs
module Permute2Tests
open Xunit
open Permutations.Permute2
[<Theory>]
[<MemberData("removeFirstTestData")>]
let ``removeFirst`` (item, list, expected: List<int>) =
let actual = removeFirst list item
Assert.Equal<List<int>>(expected, actual)
let removeFirstTestData : obj array seq =
seq {
yield [| 0; [1;2;3;4]; [1;2;3;4] |]
}
当我们运行dotnet test 时,这是错误:
System.InvalidOperationException:Permute2Tests.removeFirst 的测试数据返回 null。确保在调用此测试方法之前对其进行静态初始化。
奇怪的是,Permute1Tests.fs 运行时没有错误。它的测试通过了。而且,如果我们将ItemGroup 中的Permute1Test.fs 位置与Permute2Test.fs 交换,那么后者现在可以工作,而前者会出现错误。
我们如何在调用测试方法之前静态初始化测试数据?似乎ItemGroup 顺序在我们当前的方法中很重要,这使得我们当前的方法失败了。
以上代码的完整版is here。
编辑:ILSpy 输出
Permute1Tests.fs.cs
// <StartupCode$Permutations-Tests>.$Permute1Tests
using <StartupCode$Permutations-Tests>;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.CompilerServices;
internal static class $Permute1Tests
{
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
internal static readonly IEnumerable<object[]> permuteTestValues@12;
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
[CompilerGenerated]
[DebuggerNonUserCode]
internal static int init@;
static $Permute1Tests()
{
IEnumerable<object[]> permuteTestValues =
$Permute1Tests.permuteTestValues@12 =
(IEnumerable<object[]>)new Permute1Tests.permuteTestValues@14(0, null);
}
}
Permute2Tests.fs.cs
// <StartupCode$Permutations-Tests>.$Permute2Tests
using <StartupCode$Permutations-Tests>;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.CompilerServices;
internal static class $Permute2Tests
{
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
internal static IEnumerable<object[]> removeFirstTestData@15;
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
[CompilerGenerated]
[DebuggerNonUserCode]
internal static int init@;
public static void main@()
{
IEnumerable<object[]> removeFirstTestData =
$Permute2Tests.removeFirstTestData@15 =
(IEnumerable<object[]>)new Permute2Tests.removeFirstTestData@17(0, null);
}
}
Permutations.Test.fsproj
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.0</TargetFramework>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<Compile Include="Permute1Tests.fs" />
<Compile Include="Permute2Tests.fs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.5.0" />
<PackageReference Include="xunit" Version="2.3.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" />
<DotNetCliToolReference Include="dotnet-xunit" Version="2.3.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Permutations\Permutations.fsproj" />
</ItemGroup>
</Project>
【问题讨论】:
-
你能用ILSpy看一下编译后的代码,看看这两个模块是否在某些方面有所不同吗?如果这不能让您发现问题,请将 ILSpy 反编译结果发布到 C#。
-
我可以确认这两个模块没有区别。最不寻常的是,如果我们交换 *.fsproj ItemGroup 列表中两个文件的顺序,那么错误会发生在相反的文件中。这证明模块之间的唯一区别是它们出现在 ItemGroup 列表中的顺序。 @FyodorSoikin
-
能把ILSpy反编译的结果贴出来吗?
-
@FyodorSoikin 我已经添加了 ILSpy 输出,它确实提供了一些见解。
-
几乎明白了!您还可以发布您的
fsproj文件的完整 内容吗?