Я пишу блок-тесты С#, используя NUnit и NSubstitute. Я тестирую класс, который попытается извлечь объекты из поставщика конфигурации, реализующего следующий интерфейс:
public interface IConfigProvider<T> {
T GetConfig(int id);
T GetConfig(string id);
}
Проверяемый класс использует только версию int GetConfig
, поэтому в 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 для запуска тестов Received
, а затем запускаю только тесты конфигурации, тесты конфигурации не сработают. Если я затем снова запустим тесты конфигурации, они пройдут.
Вещи, которые я пробовал:
- Добавление
configProvider.GetConfig(Arg.Any<string>()).Returns...
также в случае, если проблема перегрузки была проблемой. - Я прочитал документы NSubstitute по сопоставлению аргументов, но я не могу найти там решение. Если это случай, когда необходимо предоставить аргументы для обеих версий метода int и string, я не могу решить, как это сделать.
Как это бывает, тесты, которые я использую, будут когда-либо вызывать метод GetConfig
со значениями 0 или 1, поэтому я могу просто предоставить спецификации Returns
для этих двух значений и не использовать совпадение вообще, но Я хочу понять, как это сделать в целом.