为什么在AutoDataAttribute实现中添加到Autofixture Fixture.Behaviors时,跟踪行为似乎不起作用?

时间:2013-09-03 22:23:34

标签: autofixture

当我使用

向AutoFixture TracingBehavior实例添加新的Fixture
fixture.Behaviors.Add(new TracingBehavior());

我在R#Unit Test Sessions窗口中获得了跟踪输出。

但是,当我继承AutoDataAttribute并在我的属性构造函数中添加行为时,就像这样

我没有获得跟踪输出,即使测试表明在两种情况下TracingBehavior都已添加到Fixture.Behaviors。下面是两个简单的测试和要重现的属性实现。

public class TracingBehaviorTests
{
    [Theory, AutoData]
    public void TracingOutputDisplayedWhenManuallyAddedToFixture(Fixture fixture)
    {
        fixture.Behaviors.Add(new TracingBehavior());
        var actual = fixture.Behaviors.OfType<TracingBehavior>().Any();
        Assert.Equal(true, actual); // Passes
        fixture.Create<string>();   // Tracing output displayed
    }

    [Theory, TracingFixtureConventions]
    public void TracingOutputDisplayedWhenUsingTracingFixtureConventionsAttribute(Fixture fixture)
    {
        var actual = fixture.Behaviors.OfType<TracingBehavior>().Any();
        Assert.Equal(true, actual); // Passes
        fixture.Create<string>();   // No tracing output displayed
    }
}

public class TracingFixtureConventionsAttribute : AutoDataAttribute
{
    public TracingFixtureConventionsAttribute()
        : base(new Fixture())
    {
        this.Fixture.Behaviors.Add(new TracingBehavior());
    }
}

1 个答案:

答案 0 :(得分:3)

我不得不做一些挖掘来弄清楚为什么会发生这种情况。

您看到此行为的原因是,当您使用TracingBehavior的默认构造函数时,Console.Out是目标。

执行测试用例时,xUnit.net测试运行器assigns another TextWriter to Console.Out

这在测试方法中的代码块执行之前发生,这解释了为什么OP中的第一个测试显示跟踪:创建TracingBehavior实例时,Console.Out已经 抓取的TextWriter

但是,在第二个测试中(使用[TracingFixtureConventions]属性),当属性的构造函数运行时,Console.Out尚未被替换。因此,当此测试运行时,它实际上会追溯到原始 Console.Out,但由于没有控制台存在,因此它会跟踪到空白。

您可以通过登录文件来验证两个测试用例实际执行日志:

public class TracingBehaviorTests
{
    [Theory, AutoData]
    public void TracingOutputDisplayedWhenManuallyAddedToFixture(Fixture fixture)
    {
        using (var tw = File.AppendText(Path.Combine(Environment.CurrentDirectory, "log.txt")))
        {
            tw.AutoFlush = true;
            fixture.Behaviors.Add(new TracingBehavior(tw));
            var actual = fixture.Behaviors.OfType<TracingBehavior>().Any();
            Assert.Equal(true, actual); // Passes
            fixture.Create<string>();   // Tracing output logged to file
        }
    }

    [Theory, TracingFixtureConventions]
    public void TracingOutputDisplayedWhenUsingTracingFixtureConventionsAttribute(Fixture fixture)
    {
        var actual = fixture.Behaviors.OfType<TracingBehavior>().Any();
        Assert.Equal(true, actual); // Passes
        fixture.Create<string>();   // Tracing output logged to file
    }
}

public class TracingFixtureConventionsAttribute : AutoDataAttribute
{
    public TracingFixtureConventionsAttribute()
        : base(new Fixture())
    {
        var tw = File.AppendText(Path.Combine(Environment.CurrentDirectory, "log.txt"));
        tw.AutoFlush = true;
        this.Fixture.Behaviors.Add(new TracingBehavior(tw));
    }
}

上述“修复”相当脆弱,因为(如此处所写)[TracingFixtureConventions]属性不会处置tw,因此如果使用[TracingFixtureConventions]属性装饰的测试运行首先,日志文件正在使用中,而另一个测试将无法写入。

现在,我将把它作为练习留给读者来弄清楚如何使文件记录更加健壮,如果这是任何人都在关心的事情。就个人而言,我只使用AutoFixture跟踪进行故障排除,并在我完成故障排除后再次将其关闭。