我正在使用NUnit和NSubstitute编写C#单元测试。我正在测试一个类,它将尝试从实现以下接口(interface)的配置提供程序中检索对象:
public interface IConfigProvider<T> {
T GetConfig(int id);
T GetConfig(string id);
}
被测试的类仅使用
GetConfig
的int版本,因此在SetUpFixture中,我执行以下操作来设置模拟的配置提供程序,该提供程序将始终返回相同的伪对象:IConfigProvider<ConfigType> configProvider = Substitute.For<IConfigProvider<ConfigType>>();
configProvider.GetConfig(Arg.Any<int>()).Returns<ConfigType>(new ConfigType(/* args */);
如果该TestFixture是唯一正在运行的程序,则这绝对可以运行。但是,在同一程序集中的另一个TestFixture中,我检查是否收到了这样的调用:
connection.Received(1).SetCallbacks(Arg.Any<Action<Message>>(), Arg.Any<Action<long>>(), Arg.Any<Action<long, Exception>>());
如果这些
Received
测试在配置提供程序测试之前运行,则配置测试在SetUpFixture中失败,并带有AmbiguousArgumentsException:Here.Be.Namespace.ProfileManagerTests+Setup (TestFixtureSetUp):
SetUp : 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)
at System.Linq.Enumerable.<SelectIterator>d__7`2.MoveNext()
at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
at NSubstitute.Core.Arguments.MixedArgumentSpecificationsFactory.Create(IList`1 argumentSpecs, Object[] arguments, IParameterInfo[] parameterInfos)
at NSubstitute.Core.Arguments.ArgumentSpecificationsFactory.Create(IList`1 argumentSpecs, Object[] arguments, IParameterInfo[] parameterInfos, MatchArgs matchArgs)
at NSubstitute.Core.CallSpecificationFactory.CreateFrom(ICall call, MatchArgs matchArgs)
at NSubstitute.Routing.Handlers.RecordCallSpecificationHandler.Handle(ICall call)
at System.Linq.Enumerable.WhereSelectArrayIterator`2.MoveNext()
at System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable`1 source, Func`2 predicate)
at NSubstitute.Routing.Route.Handle(ICall call)
at NSubstitute.Proxies.CastleDynamicProxy.CastleForwardingInterceptor.Intercept(IInvocation invocation)
at Castle.DynamicProxy.AbstractInvocation.Proceed()
at Castle.Proxies.IConfigProvider`1Proxy.GetConfig(Int32 id)
at Here.Be.Namespace.ProfileManagerTests.Setup.DoSetup()
真正令我困惑的是,即使在测试运行之间,我也能观察到这种效果-如果我使用NUnit GUI单独运行
Received
测试,然后单独运行配置测试,则配置测试将失败。如果然后立即再次运行配置测试,它们将通过。我尝试过的事情:
configProvider.GetConfig(Arg.Any<string>()).Returns...
。 碰巧的是,我正在使用的测试只会调用值为0或1的
GetConfig
方法,因此我只能为这两个值提供Returns
规范,而根本不使用匹配,但我想了解如何解决这更普遍。 最佳答案
模棱两可的参数是当NSubstitute将参数与其当前正在使用的调用进行比较时,与它具有的“参数匹配器”堆栈进行比较(每次调用Arg.Blah
时,都会将参数匹配器添加到该堆栈中),并且无法解决哪个论点去哪儿。
通常,这是由像blah(null, null)
这样的调用引起的,其中有单个参数匹配器排队,但也可能是由于在调用配置之外使用了arg匹配器而导致堆栈不同步导致的。非虚拟方法。
1.8.0版(在您的问题后发布)对后一种情况的检测略有改进,因此可能值得尝试。
除此之外,我已经遇到过几次这个问题,并使用了以下(痛苦的)方法。
Arg.xyz
的任何调用,这些调用可能会使两个测试中的参数匹配器排队。确保将其用作调用配置的一部分。有时,可以通过注释掉行或用其他值替换arg匹配器来确定哪个调用有问题。 有时问题可能是由于先前的固定装置引起的,因此您可能需要锻炼先前的固定装置并在那里进行探索。 :(
关于c# - NSubstitute-TestFixture 1导致TestFixture 2中的AmbiguousArgumentsException,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/26805420/