运行所有测试时测试失败,但逐个运行它们时成功。

4

我有4个测试分布在3个测试类中。如果我一个一个地运行每个测试,它们都可以成功。但是同时运行(并行?)时,除了第一个触发的测试外,所有测试都失败了。

我的测试需要相同的设置,因此我有一个所有测试都使用的框架:

public class CompositionRootFixture
{
    public Container Container { get; private set; } // Simple Injector Container

    public CompositionRootFixture()
    {
        Container = new Container();

        /* code removed for clearity */

        Container.Verify();
    }
}

并且可以像下面这样在我的测试类中使用:

public class CommandProcessorTests : IClassFixture<CompositionRootFixture>
{
    private readonly CompositionRootFixture _fixture;

    public CommandProcessorTests(CompositionRootFixture fixture)
    {
        _fixture = fixture;
    }

    [Fact]
    public async Task TestExecutingUsingContainerForResolution()
    {
        var commands = _fixture.Container.GetInstance<IExecuteCommands>();
        var command = new FakeCommandWithoutValidator();
        await commands.Execute(command);

        Assert.Equal("faked", command.ReturnValue);
    }
}

我很难理解如何使用 IClassFixture<T>,而且文档在设置方面并没有提供太多帮助。我正在使用最新的 XUnit 2.0.0-beta5-build2785 版本。

失败描述:

---- System.InvalidOperationException : The configuration is invalid. Creating the instance for type IHandleCommand<FakeCommandWithoutValidator> failed. The registered delegate for type IHandleCommand<FakeCommandWithoutValidator> threw an exception. The configuration is invalid. The type HandleFakeCommandWithoutValidator is directly or indirectly depending on itself.
-------- SimpleInjector.ActivationException : The registered delegate for type IHandleCommand<FakeCommandWithoutValidator> threw an exception. The configuration is invalid. The type HandleFakeCommandWithoutValidator is directly or indirectly depending on itself.
------------ SimpleInjector.ActivationException : The configuration is invalid. The type HandleFakeCommandWithoutValidator is directly or indirectly depending on itself.
---- The following constructor parameters did not have matching fixture data: CompositionRootFixture fixture

根据我的经验,容器的验证几乎从不出错。因此,如果它说“HandleFakeCommandWithoutValidator直接或间接依赖于自身”,那么很可能是真的。仔细检查您的配置,因为循环依赖是一件坏事,即使不使用容器也是如此。如果它只有时而失败,那么您是否在每个测试中以不同的方式配置容器呢? - Steven
1
只有通过xunit运行全部测试时,这些测试才会失败,逐个运行它们并不会导致失败。我需要查看容器的配置情况。也许在每个测试后进行处理,或者完全删除我的装置,并在每个测试中设置它。 - janhartmann
@meep 你能否在一个简单的项目中复现这个问题,并将该项目上传到simple injector论坛 - qujck
1
是的,我相信我可以。我需要先下班回家,但完成后我会发布它 - 谢谢。 - janhartmann
5个回答

3

您的容器正在利用单例模式,该模式在执行所有测试期间维护状态。

请在每个测试之前初始化此单例模式。


0

0

看起来这可能与SimpleInjector中的一个错误有关:

http://simpleinjector.codeplex.com/discussions/259167

无论如何,问题出在依赖注入上。如果这个 bug 没有被修复,你可以尝试使用不同的 IoC 容器,比如 Ninject,至少可以进行比较。

1
您所参考的页面描述了一个问题,该问题存在于文档代码示例中的v1版本中,正如您在该线程中看到的那样,该问题已于2011年5月得到修复。因此,我认为这个问题在所有这些年过后仍然存在的可能性非常小,特别是考虑到ASP.NET集成包的测试覆盖率以及每天使用该包的开发人员数量。 - Steven

0
希望这能帮助到某些人,但我必须确保每个单元/集成测试项目都直接引用Xunit作为Nuget包。我以为只需要有一个基本的测试项目并通过它引用Xunit就足够了。结果发现这会导致许多问题,比如不确定的测试或测试成功运行但在并行运行时失败。

0

我在我的场景中遇到了同样的问题(一些集成测试针对EventStore运行测试),尽管我没有使用ClassFixture。

xUnit测试的想法是可以并行运行每个Fact。如果您想避免这种情况,可以在某些程序集类上添加以下内容:

[assembly: CollectionBehavior(DisableTestParallelization = true)]

它们将按顺序运行。

注意: 理想情况下,应该避免这种情况,因为设计测试和代码时最好使其幂等和无状态。事实上,我将所有的测试都作为这个子类使用,以获得良好的Given Then When结构:

public abstract class Given_When_Then_Test
    : IDisposable
{
    protected Given_When_Then_Test()
    {
        Setup();
    }

    private void Setup()
    {
        Given();
        When();
    }

    protected abstract void Given();

    protected abstract void When();

    public void Dispose()
    {
        Cleanup();
    }

    protected virtual void Cleanup()
    {
    }
}

我发现的事情:

  1. 当我使用Autofac的IContainer来解析服务时,如果不先解析IComponentContext然后再用它来解析我的服务,则在并行运行集成测试时会遇到错误。

这是我为我的问题打开的另一个问题,它与并行执行xUnit的方式类似,总是会导致一个测试失败: https://dev59.com/qjQBtIcB2Jgan1zn_tBP - diegosasw

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接