【问题标题】:NUniteLite 3.11.0 throwing Null Reference Exception with AutoRun in LINQpadNUniteLite 3.11.0 在 LINQpad 中使用 AutoRun 引发 Null 引用异常
【发布时间】:2018-10-18 22:55:15
【问题描述】:

以下 LINQPad 查询在 try-catch 块中抛出 NullReferenceException

void Main()
{
    var specialFolder = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
    var workingFolder = $@"{specialFolder}\NUnitLiteTestResults";
    var args = new[]
        {
            "--labels=All",
            "--nocolor",
            "--noheader",
            $"--work={workingFolder}"
        };

    try
    {
        (new AutoRun()).Execute(args);
    }
    catch (NullReferenceException ex)
    {
        ex.Dump("why?");
    }
}

public class Runner
{
    /*
        public static int Main(string[] args) {
            return new AutoRun(Assembly.GetCallingAssembly()).Execute(new String[] {"--labels=All"});
        }
    */
    [TestFixture]
    public class FooTest
    {
        [Test]
        public void ShouldCheckBoolean()
        {
            Assert.IsTrue(true);
        }

        [Test]
        public void ShouldCompareNumbers()
        {
            Assert.AreEqual(2, 2);
        }

        [Test]
        public void ShouldCompareStrings()
        {
            Assert.AreEqual("abc", "abc");
        }

        [Test]
        public void TestCompareLists()
        {
            Assert.AreEqual(new int[] { 1, 2, 3 }, new int[] { 1, 2, 3 });
        }
    }
}

我在这里缺少任何设置代码吗?

异常(我的机器上没有C:\src\nunit 文件夹):

Object reference not set to an instance of an object.
 at System.IO.TextWriter.Dispose()
   at System.IO.TextWriter.Dispose()
   at System.IO.TextWriter.SyncTextWriter.Dispose(Boolean disposing)
   at System.IO.TextWriter.Dispose()
   at NUnit.Common.ExtendedTextWrapper.Dispose(Boolean disposing) in C:\src\nunit\nunit\src\NUnitFramework\nunitlite\ExtendedTextWrapper.cs:line 83
   at System.IO.TextWriter.Dispose()
   at NUnitLite.TextRunner.Execute(String[] args) in C:\src\nunit\nunit\src\NUnitFramework\nunitlite\TextRunner.cs:line 149
   at NUnitLite.AutoRun.Execute(String[] args) in C:\src\nunit\nunit\src\NUnitFramework\nunitlite\AutoRun.cs:line 82
   at UserQuery.Main()

【问题讨论】:

  • 可以添加异常堆栈跟踪吗?
  • 您是否添加了(通过 Linqpad)对 NUnit 框架和 NUnitLite 的引用?
  • 我只通过 LINQPad 添加了NUnitLite NuGet 包。

标签: c# nunit linqpad nunit-3.0


【解决方案1】:

问题在于运行程序试图处理 linqpad 正在使用的输出和错误流。最终,由于它当前正在使用并且打算保持打开状态,因此会导致错误。

如果将输出和错误流重定向到控制台本身的文件或运行器的参数(--out--err 参数),则可以避免此问题。

不过,在 linqpad 中运行它的全部目的是让结果显示在结果窗格中。所以你可以做的是在忽略 dispose 调用的流周围创建一个包装器。

void Main()
{
    var workDir = Path.Combine(Util.MyQueriesFolder, "nunit-work");
    var args = new string[]
    {
        "-noh",
        $"--work={workDir}",
    };
    RunUnitTests(args);
}

void RunUnitTests(string[] args, Assembly assembly = null)
{
    Console.SetOut(new NoDisposeTextWriter(Console.Out));
    Console.SetError(new NoDisposeTextWriter(Console.Error));
    new AutoRun(assembly ?? Assembly.GetExecutingAssembly()).Execute(args);
}

class NoDisposeTextWriter : TextWriter
{
    private readonly TextWriter writer;
    public NoDisposeTextWriter(TextWriter writer) => this.writer = writer;

    public override Encoding Encoding => writer.Encoding;
    public override IFormatProvider FormatProvider => writer.FormatProvider;
    public override void Write(char value) => writer.Write(value);
    public override void Flush() => writer.Flush();
    // forward all other overrides as necessary

    protected override void Dispose(bool disposing)
    {
        // no nothing
    }
}

【讨论】:

    【解决方案2】:

    根据 Jeff 的上述回答,将 NoDisposeTextWriter 作为您的 MyExtensions 中的公共类,因此它始终可用。

    那么你的 main 可以如下所示:

    void Main()
    {
        var cwd = Util.MyQueriesFolder;
        var args = new[] {
            "-noheader", 
            $"-work:{cwd}"
        };
    
        Console.SetOut(new NoDisposeTextWriter(Console.Out));
        Console.SetError(new NoDisposeTextWriter(Console.Error));
        new AutoRun(Assembly.GetExecutingAssembly()).Execute(args);
    }
    
    public class Foo{...}
    
    [TextFixture]
    public class TestFoo{...}
    

    【讨论】:

      【解决方案3】:

      如果你想从 Jeff 的回答中减少 LOC,你可以安装 FakeItEasy 并写:

      void Main()
      {
          Console.SetOut(A.Fake<TextWriter>(o => o.Wrapping(Console.Out).ConfigureFake(f => A.CallTo(f).Where(m => m.Method.Name == "Dispose").DoesNothing())));
          Console.SetError(A.Fake<TextWriter>(o => o.Wrapping(Console.Error).ConfigureFake(f => A.CallTo(f).Where(m => m.Method.Name == "Dispose").DoesNothing())));
          new AutoRun().Execute(new string[]  {"-noh", $"--work={Path.Combine(Util.MyQueriesFolder, "nunit-work")}" }); //https://stackoverflow.com/a/69205831/2086
      }
       
      [Test]
      public void SomeTest()
      {
          Assert.Pass();
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-01-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-02-28
        • 1970-01-01
        • 2014-11-07
        相关资源
        最近更新 更多