NSubstitute - 请使用相同类型的所有参数的规范。 TeamCity问题

时间:2017-03-23 09:16:41

标签: c# unit-testing autofixture

我使用AutoFixture,NSubstitute和xUnit进行单元测试。

它在VS中传递本地开发机器但在TeamCity上失败。

测试:

        [Theory, AutoNSubstituteData]
    public async void GetList_StatusError_ShouldReturnBadRequest(
        [Frozen] ICommentsService _commentsService,
        [Frozen] IMerchantsService _merchantsService,
        [Frozen] ICampaignsService _campaignsService)
    {
        // Arrange   

        var output = _fixture.Build<CommentsResult<CommentOutput>>()
            .Without(w => w.Entity)
            .With(x => x.Status, ServiceActionStatus.Error)
            .Create();

        _commentsService.List(Arg.Any<int>(), Arg.Any<string>()).Returns(output);

        var controller = new CommentController(_commentsService, _merchantsService, _campaignsService);
        controller.Request = new HttpRequestMessage();
        controller.Configuration = new HttpConfiguration();

        // Act
        IHttpActionResult actionResult = await controller.GetList(null);
        var contentResult = actionResult as BadRequestErrorMessageResult;

        // Assert
        contentResult.Should().NotBeNull();
        contentResult.Message.Should().NotBeNullOrEmpty();
    }

TeamCity错误:

    NSubstitute.Exceptions.AmbiguousArgumentsException: 
    Cannot determine argument specifications to use.
    Please use specifications for all arguments of the same type. at          NSubstitute.Core.Arguments.NonParamsArgumentSpecificationFactory.Create(Object argument, IParameterInfo parameterInfo, ISuppliedArgumentSpecifications suppliedArgumentSpecifications)

CommentsResult看起来像:

    public class CommentsResult<T> : IServiceResult<T>
    {
    public T Entity { get; set; }
    public string Message { get; set; }
    public Exception Exception { get; set; }
    public ServiceActionStatus Status { get; set; }
     }

可以是什么?

1 个答案:

答案 0 :(得分:1)

通常这个问题是由于参数规范未完全消耗而发生的(例如,您将Arg.Any<T>()传递给非虚方法)。有很多潜在的情况如何发生。您在特定环境中看到的原因可能是损坏的测试和并发性的组合(来自一个测试的垃圾在其他测试中消耗,似乎在同一个线程上运行)。这里的主要问题是,如果你有很多测试,可能真的很难解决问题,因为每个测试都可能泄漏参数规范。

最近,我创建了一个诊断套件来帮助解决此问题。它可以让你找到&#34;泄露&#34;参数规范。请注意,它可能会显着减慢测试执行速度,因此应该在之后禁用。

步骤如下:

  1. 使用测试将DiagnosticsSubstitutionContext.cs文件复制到您的项目中。
  2. 通过记录或重新抛出包含所有排队规范的信息的自定义异常来修改appropriate place。下次抛出AmbiguousArgumentsException异常时,此陷阱应该捕获一个罪魁祸首 - 规范是以前测试执行的剩余部分。 SpecCreationStack字段值可帮助您找到确切的位置。
  3. 调整代码以在执行测试之前触发DiagnosticsSubstitutionContext类的静态构造函数。例如,您可以在AutoNSubstituteData属性类中创建一个静态构造函数,其中包含以下内容:

    DiagnosticsSubstitutionContext.Init()
    
  4. 下次抛出异常后,你应该掌握有关破坏规格的信息,这样你就能找到一个确切的位置。

    P.S。如果在执行测试期间保留.pdb个文件,除了方法名称之外,您应该能够看到破坏规范排队的确切代码行。