我使用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; }
}
可以是什么?
答案 0 :(得分:1)
通常这个问题是由于参数规范未完全消耗而发生的(例如,您将Arg.Any<T>()
传递给非虚方法)。有很多潜在的情况如何发生。您在特定环境中看到的原因可能是损坏的测试和并发性的组合(来自一个测试的垃圾在其他测试中消耗,似乎在同一个线程上运行)。这里的主要问题是,如果你有很多测试,可能真的很难解决问题,因为每个测试都可能泄漏参数规范。
最近,我创建了一个诊断套件来帮助解决此问题。它可以让你找到&#34;泄露&#34;参数规范。请注意,它可能会显着减慢测试执行速度,因此应该在之后禁用。
步骤如下:
AmbiguousArgumentsException
异常时,此陷阱应该捕获一个罪魁祸首 - 规范是以前测试执行的剩余部分。 Spec
和CreationStack
字段值可帮助您找到确切的位置。调整代码以在执行测试之前触发DiagnosticsSubstitutionContext
类的静态构造函数。例如,您可以在AutoNSubstituteData
属性类中创建一个静态构造函数,其中包含以下内容:
DiagnosticsSubstitutionContext.Init()
下次抛出异常后,你应该掌握有关破坏规格的信息,这样你就能找到一个确切的位置。
P.S。如果在执行测试期间保留.pdb个文件,除了方法名称之外,您应该能够看到破坏规范排队的确切代码行。