Spiking configuring CallBase using returns
This commit is contained in:
Родитель
a30ca18ea1
Коммит
b3ae935769
|
@ -23,7 +23,7 @@ namespace NSubstitute.Specs
|
|||
public override void Context()
|
||||
{
|
||||
_call = mock<ICall>();
|
||||
_callInfo = new CallInfo(new Argument[0]);
|
||||
_callInfo = new CallInfo(new Argument[0], null);
|
||||
_callInfoFactory = mock<ICallInfoFactory>();
|
||||
_callInfoFactory.stub(x => x.Create(_call)).Return(_callInfo);
|
||||
}
|
||||
|
|
|
@ -63,7 +63,7 @@ namespace NSubstitute.Specs
|
|||
|
||||
public override CallInfo CreateSubjectUnderTest()
|
||||
{
|
||||
return new CallInfo(_arguments);
|
||||
return new CallInfo(_arguments, null);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -72,7 +72,7 @@ namespace NSubstitute.Specs
|
|||
[Test]
|
||||
public void Match_argument_by_declared_type_when_an_exact_match_is_found()
|
||||
{
|
||||
var sut = new CallInfo(new[] { CreateArg<object>("hello"), CreateArg("world") });
|
||||
var sut = new CallInfo(new[] { CreateArg<object>("hello"), CreateArg("world") }, null);
|
||||
|
||||
Assert.That(sut.Arg<object>(), Is.EqualTo("hello"));
|
||||
Assert.That(sut.Arg<string>(), Is.EqualTo("world"));
|
||||
|
@ -81,7 +81,7 @@ namespace NSubstitute.Specs
|
|||
[Test]
|
||||
public void Match_argument_by_actual_type_when_no_declared_type_match_is_found()
|
||||
{
|
||||
var sut = new CallInfo(new[] { CreateArg<object>(123), CreateArg<object>("hello") });
|
||||
var sut = new CallInfo(new[] { CreateArg<object>(123), CreateArg<object>("hello") }, null);
|
||||
|
||||
Assert.That(sut.Arg<string>(), Is.EqualTo("hello"));
|
||||
Assert.That(sut.Arg<int>(), Is.EqualTo(123));
|
||||
|
@ -91,7 +91,7 @@ namespace NSubstitute.Specs
|
|||
public void Match_argument_by_actual_type_when_no_declared_type_match_is_found_and_when_a_compatible_argument_is_provided()
|
||||
{
|
||||
var list = new List<int>();
|
||||
var sut = new CallInfo(new[] { CreateArg<object>("asdf"), CreateArg<object>(list) });
|
||||
var sut = new CallInfo(new[] { CreateArg<object>("asdf"), CreateArg<object>(list) }, null);
|
||||
Assert.That(sut.Arg<IEnumerable<int>>(), Is.SameAs(list));
|
||||
}
|
||||
|
||||
|
@ -99,7 +99,7 @@ namespace NSubstitute.Specs
|
|||
public void Match_by_ref_type_arguments_when_argument_that_is_the_non_by_ref_type_is_provided()
|
||||
{
|
||||
const int expectedResult = 5;
|
||||
var sut = new CallInfo(new[] { CreateArg<object>("aasdf"), new ByRefArgument<int>(expectedResult) });
|
||||
var sut = new CallInfo(new[] { CreateArg<object>("aasdf"), new ByRefArgument<int>(expectedResult) }, null);
|
||||
Assert.That(sut.Arg<int>(), Is.EqualTo(expectedResult));
|
||||
}
|
||||
|
||||
|
@ -107,14 +107,14 @@ namespace NSubstitute.Specs
|
|||
public void Match_by_ref_type_arguments_when_argument_compatbile_non_by_ref_type_is_provided()
|
||||
{
|
||||
var list = new List<int>();
|
||||
var sut = new CallInfo(new[] { CreateArg<object>("aasdf"), new ByRefArgument<List<int>>(list) });
|
||||
var sut = new CallInfo(new[] { CreateArg<object>("aasdf"), new ByRefArgument<List<int>>(list) }, null);
|
||||
Assert.That(sut.Arg<IEnumerable<int>>(), Is.EqualTo(list));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Throw_when_there_is_no_declared_type_match_but_multiple_compatible_arguments()
|
||||
{
|
||||
var sut = new CallInfo(new[] { CreateArg<object>("a"), CreateArg<object>("b") });
|
||||
var sut = new CallInfo(new[] { CreateArg<object>("a"), CreateArg<object>("b") }, null);
|
||||
Assert.Throws<AmbiguousArgumentsException>(() => sut.Arg<string>());
|
||||
}
|
||||
}
|
||||
|
@ -124,7 +124,7 @@ namespace NSubstitute.Specs
|
|||
[Test]
|
||||
public void Throw_when_setting_argument_that_is_not_passed_by_ref()
|
||||
{
|
||||
var sut = new CallInfo(new[] { CreateArg(1) });
|
||||
var sut = new CallInfo(new[] { CreateArg(1) }, null);
|
||||
|
||||
Assert.Throws<ArgumentIsNotOutOrRefException>(() => sut[0] = 123);
|
||||
}
|
||||
|
@ -132,7 +132,7 @@ namespace NSubstitute.Specs
|
|||
[Test]
|
||||
public void Throw_when_setting_by_ref_argument_with_an_incompatible_value()
|
||||
{
|
||||
var sut = new CallInfo(new[] { new ByRefArgument<object>("needs a string") });
|
||||
var sut = new CallInfo(new[] { new ByRefArgument<object>("needs a string") }, null);
|
||||
|
||||
Assert.Throws<ArgumentSetWithIncompatibleValueException>(() => sut[0] = new object());
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ namespace NSubstitute.Specs
|
|||
|
||||
protected CallInfo StubCallInfoForCall(ICall call)
|
||||
{
|
||||
var callInfo = new CallInfo(new Argument[0]);
|
||||
var callInfo = new CallInfo(new Argument[0], null);
|
||||
_callInfoFactory.stub(x => x.Create(call)).Return(callInfo);
|
||||
return callInfo;
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ namespace NSubstitute.Specs
|
|||
|
||||
public override void Context()
|
||||
{
|
||||
_callInfo = new CallInfo(new Argument[0]);
|
||||
_callInfo = new CallInfo(new Argument[0], null);
|
||||
_func = mock<Func<CallInfo, string>>();
|
||||
_func.stub(x => x(_callInfo)).Return(ValueToReturn);
|
||||
}
|
||||
|
@ -44,7 +44,7 @@ namespace NSubstitute.Specs
|
|||
[Test]
|
||||
public void Should_return_null()
|
||||
{
|
||||
Assert.That(sut.ReturnFor(new CallInfo(new Argument[0])), Is.Null);
|
||||
Assert.That(sut.ReturnFor(new CallInfo(new Argument[0], null)), Is.Null);
|
||||
}
|
||||
|
||||
public override ReturnValueFromFunc<string> CreateSubjectUnderTest()
|
||||
|
|
|
@ -1,20 +0,0 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace NSubstitute.Core
|
||||
{
|
||||
public class CallBaseSpecifications : ICallBaseSpecifications
|
||||
{
|
||||
readonly List<ICallSpecification> _callSpecifications = new List<ICallSpecification>();
|
||||
|
||||
public void Add(ICallSpecification callSpecification)
|
||||
{
|
||||
_callSpecifications.Add(callSpecification);
|
||||
}
|
||||
|
||||
public bool DoesCallBase(ICall callInfo)
|
||||
{
|
||||
return _callSpecifications.Any(cs => cs.IsSatisfiedBy(callInfo));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -8,12 +8,19 @@ namespace NSubstitute.Core
|
|||
public class CallInfo
|
||||
{
|
||||
private readonly Argument[] _callArguments;
|
||||
private readonly Func<object> _callBase;
|
||||
|
||||
public CallInfo(Argument[] callArguments)
|
||||
public CallInfo(Argument[] callArguments, Func<object> callBase)
|
||||
{
|
||||
_callArguments = callArguments;
|
||||
_callBase = callBase;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the nth argument to this call.
|
||||
/// </summary>
|
||||
/// <param name="index">Index of argument</param>
|
||||
/// <returns>The value of the argument at the given index</returns>
|
||||
public object this[int index]
|
||||
{
|
||||
get { return _callArguments[index].Value; }
|
||||
|
@ -38,16 +45,30 @@ namespace NSubstitute.Core
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the arguments passed to this call.
|
||||
/// </summary>
|
||||
/// <returns>Array of all arguments passed to this call</returns>
|
||||
public object[] Args()
|
||||
{
|
||||
return _callArguments.Select(x => x.Value).ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the types of all the arguments passed to this call.
|
||||
/// </summary>
|
||||
/// <returns>Array of types of all arguments passed to this call</returns>
|
||||
public Type[] ArgTypes()
|
||||
{
|
||||
return _callArguments.Select(x => x.DeclaredType).ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the argument of type `T` passed to this call. This will throw if there are no arguments
|
||||
/// of this type, or if there is more than one matching argument.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the argument to retrieve</typeparam>
|
||||
/// <returns>The argument passed to the call, or throws if there is not exactly one argument of this type</returns>
|
||||
public T Arg<T>()
|
||||
{
|
||||
T arg;
|
||||
|
@ -56,6 +77,15 @@ namespace NSubstitute.Core
|
|||
throw new ArgumentNotFoundException("Can not find an argument of type " + typeof(T).FullName + " to this call.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Call the underlying base implementation of this call, if this is for a virtual member.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public object CallBase()
|
||||
{
|
||||
return _callBase();
|
||||
}
|
||||
|
||||
private bool TryGetArg<T>(Func<Argument, bool> condition, out T value)
|
||||
{
|
||||
value = default(T);
|
||||
|
|
|
@ -9,7 +9,7 @@ namespace NSubstitute.Core
|
|||
public CallInfo Create(ICall call)
|
||||
{
|
||||
var arguments = GetArgumentsFromCall(call).ToArray();
|
||||
return new CallInfo(arguments);
|
||||
return new CallInfo(arguments, call.CallBase);
|
||||
}
|
||||
|
||||
private static IEnumerable<Argument> GetArgumentsFromCall(ICall call)
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
namespace NSubstitute.Core
|
||||
{
|
||||
public interface ICallBaseSpecifications
|
||||
{
|
||||
void Add(ICallSpecification callSpecification);
|
||||
bool DoesCallBase(ICall callInfo);
|
||||
}
|
||||
}
|
|
@ -1,5 +1,4 @@
|
|||
using System;
|
||||
using NSubstitute.Routing.AutoValues;
|
||||
using NSubstitute.Routing.AutoValues;
|
||||
|
||||
namespace NSubstitute.Core
|
||||
{
|
||||
|
@ -12,7 +11,6 @@ namespace NSubstitute.Core
|
|||
ICallResults CallResults { get; }
|
||||
ICallSpecificationFactory CallSpecificationFactory { get; }
|
||||
ICallActions CallActions { get; }
|
||||
ICallBaseSpecifications CallBaseSpecifications { get; }
|
||||
bool CallBaseByDefault { get; set; }
|
||||
SequenceNumberGenerator SequenceNumberGenerator { get; }
|
||||
IConfigureCall ConfigureCall { get; }
|
||||
|
|
|
@ -11,7 +11,6 @@ namespace NSubstitute.Core
|
|||
public ICallResults CallResults { get; private set; }
|
||||
public ICallSpecificationFactory CallSpecificationFactory { get; private set; }
|
||||
public ICallActions CallActions { get; private set; }
|
||||
public ICallBaseSpecifications CallBaseSpecifications { get; private set; }
|
||||
public bool CallBaseByDefault { get; set; }
|
||||
public SequenceNumberGenerator SequenceNumberGenerator { get; private set; }
|
||||
public IConfigureCall ConfigureCall { get; private set; }
|
||||
|
@ -31,7 +30,6 @@ namespace NSubstitute.Core
|
|||
CallResults = new CallResults(callInfoFactory);
|
||||
CallSpecificationFactory = CallSpecificationFactoryFactoryYesThatsRight.CreateCallSpecFactory();
|
||||
CallActions = new CallActions(callInfoFactory);
|
||||
CallBaseSpecifications = new CallBaseSpecifications();
|
||||
|
||||
var getCallSpec = new GetCallSpec(callStack, PendingSpecification, CallSpecificationFactory, CallActions);
|
||||
|
||||
|
|
|
@ -115,7 +115,6 @@
|
|||
<Compile Include="Core\Arguments\ParamsArgumentSpecificationFactory.cs" />
|
||||
<Compile Include="Core\Arguments\SuppliedArgumentSpecifications.cs" />
|
||||
<Compile Include="Core\Arguments\SuppliedArgumentSpecificationsFactory.cs" />
|
||||
<Compile Include="Core\CallBaseSpecifications.cs" />
|
||||
<Compile Include="Core\CallFactory.cs" />
|
||||
<Compile Include="Core\CallSpecAndTarget.cs" />
|
||||
<Compile Include="Core\CallSpecificationFactoryFactoryYesThatsRight.cs" />
|
||||
|
@ -125,7 +124,6 @@
|
|||
<Compile Include="Core\Arguments\IArgumentEqualsSpecificationFactory.cs" />
|
||||
<Compile Include="Core\Extensions.cs" />
|
||||
<Compile Include="Core\GetCallSpec.cs" />
|
||||
<Compile Include="Core\ICallBaseSpecifications.cs" />
|
||||
<Compile Include="Core\ICallRouterProvider.cs" />
|
||||
<Compile Include="Core\IGetCallSpec.cs" />
|
||||
<Compile Include="Core\SequenceChecking\InstanceTracker.cs" />
|
||||
|
@ -191,7 +189,6 @@
|
|||
<Compile Include="Core\IReturn.cs" />
|
||||
<Compile Include="Core\PropertyCallFormatter.cs" />
|
||||
<Compile Include="Core\ReflectionExtensions.cs" />
|
||||
<Compile Include="Routing\Handlers\ReturnBaseResultCallHandler.cs" />
|
||||
<Compile Include="Routing\Handlers\SetBaseForCallHandler.cs" />
|
||||
<Compile Include="Routing\IRouteFactory.cs" />
|
||||
<Compile Include="Routing\Route.cs" />
|
||||
|
|
|
@ -10,17 +10,22 @@ namespace NSubstitute.Proxies.CastleDynamicProxy
|
|||
|
||||
public virtual ICall Map(IInvocation castleInvocation)
|
||||
{
|
||||
Func<object> baseMethod = null;
|
||||
if (castleInvocation.InvocationTarget != null &&
|
||||
castleInvocation.MethodInvocationTarget.IsAbstract != true)
|
||||
{
|
||||
baseMethod = () =>
|
||||
{
|
||||
//Func<object> baseMethod = null;
|
||||
//if (castleInvocation.InvocationTarget != null &&
|
||||
// castleInvocation.MethodInvocationTarget.IsAbstract != true)
|
||||
//{
|
||||
// baseMethod = () =>
|
||||
// {
|
||||
// castleInvocation.Proceed();
|
||||
// return castleInvocation.ReturnValue;
|
||||
// };
|
||||
//}
|
||||
|
||||
Func<object> baseMethod = () =>
|
||||
{
|
||||
castleInvocation.Proceed();
|
||||
return castleInvocation.ReturnValue;
|
||||
};
|
||||
}
|
||||
|
||||
return CallFactory.Create(castleInvocation.Method, castleInvocation.Arguments, castleInvocation.Proxy, baseMethod);
|
||||
}
|
||||
|
|
|
@ -1,26 +0,0 @@
|
|||
using NSubstitute.Core;
|
||||
|
||||
namespace NSubstitute.Routing.Handlers
|
||||
{
|
||||
public class ReturnBaseResultCallHandler : ICallHandler
|
||||
{
|
||||
private readonly ISubstituteState _substituteState;
|
||||
private readonly ICallBaseSpecifications _callBaseSpecifications;
|
||||
|
||||
public ReturnBaseResultCallHandler(ISubstituteState substituteState, ICallBaseSpecifications callBaseSpecifications)
|
||||
{
|
||||
_substituteState = substituteState;
|
||||
_callBaseSpecifications = callBaseSpecifications;
|
||||
}
|
||||
|
||||
public RouteAction Handle(ICall call)
|
||||
{
|
||||
if (_callBaseSpecifications.DoesCallBase(call) || _substituteState.CallBaseByDefault)
|
||||
{
|
||||
return RouteAction.Return(call.CallBase());
|
||||
}
|
||||
|
||||
return RouteAction.Continue();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -8,13 +8,13 @@ namespace NSubstitute.Routing.Handlers
|
|||
public class SetBaseForCallHandler : ICallHandler
|
||||
{
|
||||
private readonly ICallSpecificationFactory _callSpecificationFactory;
|
||||
private readonly ICallBaseSpecifications _callBaseSpecifications;
|
||||
private readonly ICallResults _callResults;
|
||||
private readonly MatchArgs _matchArgs;
|
||||
|
||||
public SetBaseForCallHandler(ICallSpecificationFactory callSpecificationFactory, ICallBaseSpecifications callBaseSpecifications, MatchArgs matchArgs)
|
||||
public SetBaseForCallHandler(ICallSpecificationFactory callSpecificationFactory, ICallResults callResults, MatchArgs matchArgs)
|
||||
{
|
||||
_callSpecificationFactory = callSpecificationFactory;
|
||||
_callBaseSpecifications = callBaseSpecifications;
|
||||
_callResults = callResults;
|
||||
_matchArgs = matchArgs;
|
||||
}
|
||||
|
||||
|
@ -26,7 +26,7 @@ namespace NSubstitute.Routing.Handlers
|
|||
throw new CouldNotCallBaseException(method);
|
||||
}
|
||||
var callSpec = _callSpecificationFactory.CreateFrom(call, _matchArgs);
|
||||
_callBaseSpecifications.Add(callSpec);
|
||||
_callResults.SetResult(callSpec, new ReturnValueFromBase(method.ReturnType));
|
||||
return RouteAction.Continue();
|
||||
}
|
||||
|
||||
|
@ -34,5 +34,14 @@ namespace NSubstitute.Routing.Handlers
|
|||
{
|
||||
return methodInfo.IsVirtual && !methodInfo.IsFinal && !methodInfo.IsAbstract;
|
||||
}
|
||||
|
||||
class ReturnValueFromBase : IReturn
|
||||
{
|
||||
private readonly Type _expectedType;
|
||||
public ReturnValueFromBase(Type expectedType) { _expectedType = expectedType; }
|
||||
public object ReturnFor(CallInfo info) { return info.CallBase(); }
|
||||
public Type TypeOrNull() { return _expectedType; }
|
||||
public bool CanBeAssignedTo(Type t) { return _expectedType.IsAssignableFrom(t); }
|
||||
}
|
||||
}
|
||||
}
|
|
@ -11,7 +11,7 @@ namespace NSubstitute.Routing
|
|||
return new Route(new ICallHandler[] {
|
||||
new ClearLastCallRouterHandler(state.SubstitutionContext)
|
||||
, new ClearUnusedCallSpecHandler(state)
|
||||
, new SetBaseForCallHandler(state.CallSpecificationFactory, state.CallBaseSpecifications, matchArgs)
|
||||
, new SetBaseForCallHandler(state.CallSpecificationFactory, state.CallResults, matchArgs)
|
||||
, ReturnDefaultForReturnTypeHandler()
|
||||
});
|
||||
}
|
||||
|
@ -71,7 +71,6 @@ namespace NSubstitute.Routing
|
|||
, new PropertySetterHandler(new PropertyHelper(), state.ConfigureCall)
|
||||
, new DoActionsCallHandler(state.CallActions)
|
||||
, new ReturnConfiguredResultHandler(state.CallResults)
|
||||
, new ReturnBaseResultCallHandler(state, state.CallBaseSpecifications)
|
||||
, new ReturnAutoValueForThisAndSubsequentCallsHandler(state.AutoValueProviders, state.ConfigureCall)
|
||||
, ReturnDefaultForReturnTypeHandler()
|
||||
});
|
||||
|
|
Загрузка…
Ссылка в новой задаче