【发布时间】:2015-01-04 11:47:30
【问题描述】:
我正在使用 NUnit 和 NSubstitute 编写 C# 单元测试。我正在测试一个类,它将尝试从实现以下接口的配置提供程序中检索对象:
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...,以防超载是问题。 - 我已经阅读了NSubstitute docs on argument matching,但在那里我找不到解决方案。如果必须为方法的 int 和 string 版本提供参数匹配器,我不知道该怎么做。
碰巧的是,我正在使用的测试只会调用值为 0 或 1 的 GetConfig 方法,因此我可以只为这两个值提供 Returns 规范而不使用匹配,但是我想了解如何更普遍地解决此问题。
【问题讨论】:
-
您是否在
new ConfigType(/* args */)代码中使用了任何参数匹配器? -
不,我有一个枚举实例、一个字符串和一个空 List
- 只是占位符参数来创建一个足够好的对象供接收者接受。
标签: c# nunit nsubstitute