如何找到 NotSupportedException 根本原因?

How to find the NotSupportedException root cause?

我有一个针对 .net 4.6.1 项目的 netcoreapp2.0 测试项目 运行。安装 3.0 SDK 后,我开始在该项目的所有测试中抛出 NotSupportedException。在只有旧版 SDK 或在 global.json 文件中指定 2.2 SDK 的机器上它可以工作。

我的意思是,我怎样才能找到抛出异常的原因?它被扔进一个我不拥有的 DLL 中,我无法使用 sourcelink。 VS 不显示任何堆栈跟踪,即使为每个异常设置了 CLR 异常,它也不会在异常时停止。

这是我通过 运行 测试得到的唯一结果。

PS (...)> dotnet test
Test run for (...).Tests.dll(.NETCoreApp,Version=v2.2)
Microsoft (R) Test Execution Command Line Tool Version 16.3.0
Copyright (c) Microsoft Corporation.  All rights reserved.

Starting test execution, please wait...

A total of 1 test files matched the specified pattern.
[xUnit.net 00:00:01.35]     (...) [FAIL]
  X (...) [1ms]
  Error Message:
   System.NotSupportedException : Specified method is not supported.

[xUnit.net 00:00:01.43]     (...) [FAIL]
[xUnit.net 00:00:01.43]     (...) [FAIL]
[xUnit.net 00:00:01.43]     (...) [FAIL]
[xUnit.net 00:00:01.43]     (...) [FAIL]
[xUnit.net 00:00:01.43]     (...) [FAIL]
[xUnit.net 00:00:01.43]     (...) [FAIL]
[xUnit.net 00:00:01.43]     (...) [FAIL]
[xUnit.net 00:00:01.43]     (...) [FAIL]
  X (...) [1ms]
  Error Message:
   System.NotSupportedException : Specified method is not supported.

  X (...) [1ms]
  Error Message:
   System.NotSupportedException : Specified method is not supported.

  X (...) [1ms]
  Error Message:
   System.NotSupportedException : Specified method is not supported.

  X (...) [1ms]
  Error Message:
   System.NotSupportedException : Specified method is not supported.

  X (...) [1ms]
  Error Message:
   System.NotSupportedException : Specified method is not supported.

  X (...) [1ms]
  Error Message:
   System.NotSupportedException : Specified method is not supported.

  X (...) [1ms]
  Error Message:
   System.NotSupportedException : Specified method is not supported.

  X (...) [1ms]
  Error Message:
   System.NotSupportedException : Specified method is not supported.

(REPEATS FOR ALL THE TESTS...)

Test Run Failed.
Total tests: 30
     Failed: 30
 Total time: 3,2953 Seconds

更新: 我不知道如何或为什么将 VS 更新到 16.3.9(我在 16.3.8)and/or 重新启动机器它不再发生了。所有测试现在都可以运行,无需对源进行任何修改。

git status
On branch master
Your branch is up to date with 'origin/master'.

nothing to commit, working tree clean
Test run for (...).Tests.dll(.NETCoreApp,Version=v2.0)
Microsoft (R) Test Execution Command Line Tool Version 16.3.0
Copyright (c) Microsoft Corporation.  All rights reserved.

Starting test execution, please wait...

A total of 1 test files matched the specified pattern.

Test Run Successful.
Total tests: 431
     Passed: 431
 Total time: 10,5425 Seconds

虽然我无法在完全相同的情况下重现该错误,但我可能会故意收到相同的错误消息,并且可能是相关的。 我们所有的测试都装饰有 Xunit.TheoryAttribute、几个 Xunit.TraitAttribute 和许多 JsonDataSourceAttribute。最后一个是内部开发的,它从 JSON 文件创建了一个测试场景,非常像 DataSourceAttribute 所做的(如 How to: Create a data-driven unit test 中所解释的)。 即使激活 "Break When Thrown" 并在测试方法和构造函数上添加断点,当找不到测试场景文件时,我也会收到同样的错误消息,并且没有提供堆栈跟踪。

TestClassName
   Source: (...)Test.cs line 35
   Duration: 1 ms

  Message: 
    System.NotSupportedException : Specified method is not supported.

也许之前的问题与文件没有被复制到输出有关,但我仍然不知道为什么我没有得到堆栈跟踪或与找不到文件相关的更具体的错误。我将检查属性源并验证它是否可以改进,以及它是否以某种方式隐藏了问题。

通过将 JsonDataSourceAttribute 源添加到同一个解决方案中,我可以让它停止在应该的位置(在本例中为 "file not found")。

这是原始来源。异常(当强制发生时)在 if (!File.Exists(inputfile)) 上抛出,但 Xunit.Sdk.DataAttribute 隐藏它。

    public sealed class JsonDataSourceAttribute : DataAttribute
    {
        public string InputFilePath { get; }

        /// <summary>
        /// Retrieves a collection of context data
        /// </summary>
        /// <param name="inputFilePath">Json source file path</param>
        public JsonDataSourceAttribute(string inputFilePath)
        {
            this.InputFilePath = inputFilePath;
        }

        public override IEnumerable<object[]> GetData(MethodInfo testMethod)
        {
            if (testMethod == null) { throw new ArgumentNullException(nameof(testMethod)); }

            var inputfile = Path.IsPathRooted(this.InputFilePath)
                ? this.InputFilePath
                : Path.Combine(Directory.GetCurrentDirectory(), this.InputFilePath);

            if (!File.Exists(inputfile))
            {
                throw new ArgumentException($"Input file not found at '{inputfile}'.");
            }

            return this.LoadFileData(inputfile, this.EnumMap);
        }

        (...)
    }

通过将文件存在性检查移至构造函数,我能够得到我想要的。

        public JsonDataSourceAttribute(string inputFilePath)
        {
            var inputfile = Path.IsPathRooted(inputFilePath)
                ? inputFilePath
                : Path.Combine(Directory.GetCurrentDirectory(), inputFilePath);

            if (!File.Exists(inputfile))
            {
                throw new ArgumentException($"Input file not found at '{inputfile}'.");
            }

            this.InputFilePath = inputfile;
        }

这不是 "find the root cause" 的答案,但我想这是不可能的,因为在 Xunit.Sdk.DataAttribute 上省略了原始异常。