Making ArgumentSpecification able to create a copy of itself that matches

any args.

This moves the logic from CallSpecification and ArgumentSpecificationsFactory.
This commit is contained in:
David Tchepak 2011-12-15 22:37:15 +11:00
Родитель f1f137c7df
Коммит fd2679d932
5 изменённых файлов: 27 добавлений и 42 удалений

Просмотреть файл

@ -63,40 +63,34 @@ namespace NSubstitute.Specs.Arguments
public class When_creating_arg_specs_that_match_any_arguments : When_creating_argument_specifications
{
private IArgumentSpecification _anyArgsVersionOfIntSpec;
private IArgumentSpecification _anyArgsVersionOfStringSpec;
public override void Context()
{
base.Context();
_matchArgs = MatchArgs.Any;
_mixedArgumentSpecifications.Add(CreateSpecWith(typeof(int), x => { }));
_mixedArgumentSpecifications.Add(CreateSpecWith(typeof(string), x => { }));
_anyArgsVersionOfIntSpec = mock<IArgumentSpecification>();
_anyArgsVersionOfStringSpec = mock<IArgumentSpecification>();
_mixedArgumentSpecifications.Add(CreateSpecWith(typeof(int), _anyArgsVersionOfIntSpec));
_mixedArgumentSpecifications.Add(CreateSpecWith(typeof(string), _anyArgsVersionOfStringSpec));
}
[Test]
public void Should_return_arg_specs_based_on_those_worked_out_by_mixed_arg_spec_factory()
{
for (int i = 0; i < _mixedArgumentSpecifications.Count(); i++)
{
var argSpec = _result.ElementAt(i);
Assert.That(argSpec.IsSatisfiedBy(GetAnyValueFor(argSpec.ForType)), "Result should match any argument of compatible type");
Assert.That(argSpec.ForType, Is.EqualTo(_mixedArgumentSpecifications[i].ForType), "Result should be for same arg type");
Assert.That(argSpec.Action, Is.EqualTo(_mixedArgumentSpecifications[i].Action), "Result should have same specified action");
}
var resultArray = _result.ToArray();
Assert.That(resultArray[0], Is.EqualTo(_anyArgsVersionOfIntSpec), "Result should be a copy of original spec that matches any args");
Assert.That(resultArray[1], Is.SameAs(_anyArgsVersionOfStringSpec), "Result should be a copy of original spec that matches any args");
}
private object GetAnyValueFor(Type t)
{
if (t == typeof(string)) return "sample value";
if (t == typeof(int)) return 123423;
throw new ArgumentOutOfRangeException("Was not expecting type " + t.Name + ". If you added another argument specification " +
"for this type to the fixture context you'll also need to provide a sample value for it.");
}
private IArgumentSpecification CreateSpecWith(Type type, Action<object> action)
private IArgumentSpecification CreateSpecWith(Type type, IArgumentSpecification anyArgsVersionOfSpec)
{
var spec = mock<IArgumentSpecification>();
spec.stub(x => x.ForType).Return(type);
spec.Action = action;
spec.stub(x => x.CreateCopyMatchingAnyArgOfType(type)).Return(anyArgsVersionOfSpec);
return spec;
}
}

Просмотреть файл

@ -26,5 +26,16 @@ namespace NSubstitute.Core.Arguments
public Type ForType { get { return _forType; } }
public Action<object> Action { get; set; }
public override string ToString() { return _matcher.ToString(); }
public IArgumentSpecification CreateCopyMatchingAnyArgOfType(Type requiredType)
{
return new ArgumentSpecification(requiredType, new AnyArgumentMatcher(requiredType)) { Action = RunActionIfTypeIsCompatible };
}
private void RunActionIfTypeIsCompatible(object argument)
{
if (!argument.IsCompatibleWith(ForType)) return;
Action(argument);
}
}
}

Просмотреть файл

@ -17,13 +17,8 @@ namespace NSubstitute.Core.Arguments
var argumentSpecifications = _mixedArgumentSpecificationsFactory.Create(argumentSpecs, arguments, parameterInfos);
return (matchArgs == MatchArgs.Any)
? argumentSpecifications.Select(x => CreateVariantOfArgSpecThatMatchesAnyCompatibleArg(x))
? argumentSpecifications.Select(x => x.CreateCopyMatchingAnyArgOfType(x.ForType))
: argumentSpecifications;
}
private IArgumentSpecification CreateVariantOfArgSpecThatMatchesAnyCompatibleArg(IArgumentSpecification x)
{
return new ArgumentSpecification(x.ForType, new AnyArgumentMatcher(x.ForType)) { Action = x.Action};
}
}
}

Просмотреть файл

@ -7,5 +7,6 @@ namespace NSubstitute.Core.Arguments
bool IsSatisfiedBy(object argument);
Type ForType { get; }
Action<object> Action { get; set; }
IArgumentSpecification CreateCopyMatchingAnyArgOfType(Type requiredType);
}
}

Просмотреть файл

@ -1,4 +1,3 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
@ -46,7 +45,7 @@ namespace NSubstitute.Core
.GetParameters()
.Zip(
_argumentSpecifications,
(p, spec) => ConvertArgSpecToMatchAnyInstanceOfParameterType(p, spec)
(p, spec) => spec.CreateCopyMatchingAnyArgOfType(p.ParameterType)
)
.ToArray();
return new CallSpecification(_methodInfo, anyArgs);
@ -63,21 +62,6 @@ namespace NSubstitute.Core
}
}
private IArgumentSpecification ConvertArgSpecToMatchAnyInstanceOfParameterType(ParameterInfo parameter, IArgumentSpecification spec)
{
var requiredType = parameter.ParameterType;
return new ArgumentSpecification(requiredType, new AnyArgumentMatcher(requiredType))
{
Action = x => RunActionIfTypeIsCompatible(x, spec.Action, spec.ForType)
};
}
private void RunActionIfTypeIsCompatible(object argument, Action<object> action, Type requiredType)
{
if (!argument.IsCompatibleWith(requiredType)) return;
action(argument);
}
private bool HasDifferentNumberOfArguments(ICall call)
{
return _argumentSpecifications.Length != call.GetArguments().Length;