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

标签 autofixture

当我添加一个新的 TracingBehavior到自动夹具 Fixture实例使用

fixture.Behaviors.Add(new TracingBehavior());

我在我的 R# 单元测试 session 窗口中获得了跟踪输出。

但是,当我继承 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());
    }
}

最佳答案

我不得不做一些挖掘来弄清楚为什么会这样。

您看到此行为的原因是当您使用 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 跟踪来进行故障排除,并且在完成故障排除后总是再次将其关闭。

关于autofixture - 为什么在 AutoDataAttribute 实现中添加到 Autofixture Fixture.Behaviors 时,跟踪行为似乎不起作用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18602462/

相关文章:

c# - 如何强制 AutoFixture 创建 ImmutableList

autofixture - 带有嵌套集合的类 - 如何填充嵌套类?

c# - 需要为 ApiControllers 创建约定

c# - 向 AutoFixture 提供真实的 AutoMapper 实例

c# - AutoFixture.Freeze IEnumerable 模拟

autofixture - OmitAutoProperties 影响非自动属性

c# - AutoFixture - 配置夹具以限制字符串生成长度

c# - 阻止 child 在最小起订量/AutoFixture 中 mock

AutoFixture:你能解冻数据类型吗?

c# - 覆盖 Autofixture 自定义设置