Beispiel #1
0
        public void AddInvocationExecutor(IInvocation invocation, INMockitoSmartParameter[] smartParameters, IInvocationExecutor executor)
        {
            var method              = invocation.Method;
            var genericArguments    = invocation.GenericArguments;
            var methodParameters    = method.GetParameters();
            var invocationArguments = invocation.Arguments;

            // Flatten params[] of invocation arguments
            if (methodParameters.Length > 0 &&
                methodParameters.Last().GetCustomAttributes(typeof(ParamArrayAttribute), false).Length > 0 &&
                invocationArguments.Last() != null)
            {
                var paramsArray            = (Array)invocationArguments.Last();
                var newInvocationArguments = new object[invocationArguments.Length + paramsArray.Length - 1];
                var cutIndex = invocationArguments.Length - 1;
                Array.Copy(invocationArguments, newInvocationArguments, cutIndex);
                Array.Copy(paramsArray, 0, newInvocationArguments, cutIndex, paramsArray.Length);
                invocationArguments = newInvocationArguments;
            }

            // Convert all invocation arguments into eq(arg[i]) smart parameters
            if (smartParameters.Length == 0)
            {
                smartParameters = ConvertInvocationArgumentsToEqualityParameters(invocationArguments);
            }

            // Find out/ref parameters, swap them with null and record the index => smart parameter replacement.
            var refReplacementsByIndex = new List <KeyValuePair <int, object> >();

            for (var i = 0; i < methodParameters.Length; i++)
            {
                var parameter = methodParameters[i];
                if (parameter.Attributes.HasFlag(ParameterAttributes.Out))
                {
                    var replacement = invocation.Arguments[i];
                    smartParameters[i] = null;
                    refReplacementsByIndex.Add(new KeyValuePair <int, object>(i, replacement));
                }
            }

            var tracker = trackerByArguments.FirstOrDefault(kvp => kvp.Key.Item1 == method && kvp.Key.Item2 == genericArguments && SmartParametersEqual(kvp.Key.Item3, smartParameters)).Value;

            if (tracker == null)
            {
                tracker = new InvocationResultTracker(GetDefaultValue(method.ReturnType), refReplacementsByIndex);
                var key = new Tuple <MethodInfo, Type[], INMockitoSmartParameter[]>(method, genericArguments, smartParameters);
                trackerByArguments.Add(new KeyValuePair <Tuple <MethodInfo, Type[], INMockitoSmartParameter[]>, InvocationResultTracker>(key, tracker));
            }
            tracker.AddResult(executor);
        }
Beispiel #2
0
        private object GetInvocationResult(IInvocation invocation)
        {
            // Flatten params[] of invocation arguments
            var method              = invocation.Method;
            var methodParameters    = method.GetParameters();
            var invocationArguments = invocation.Arguments;

            if (methodParameters.Length > 0 &&
                methodParameters.Last().GetCustomAttributes(typeof(ParamArrayAttribute), false).Length > 0 &&
                invocationArguments.Last() != null)
            {
                var paramsArray            = (Array)invocationArguments.Last();
                var newInvocationArguments = new object[invocationArguments.Length + paramsArray.Length - 1];
                var cutIndex = invocationArguments.Length - 1;
                Array.Copy(invocationArguments, newInvocationArguments, cutIndex);
                Array.Copy(paramsArray, 0, newInvocationArguments, cutIndex, paramsArray.Length);
                invocationArguments = newInvocationArguments;
            }

            // Try to find our invocation result tracker... can't use dictionary comparers
            InvocationResultTracker tracker = null;

            foreach (var kvp in trackerByArguments)
            {
                if (invocation.Method == kvp.Key.Item1 &&
                    ((invocation.GenericArguments == null && kvp.Key.Item2 == null) || Enumerable.SequenceEqual(invocation.GenericArguments, kvp.Key.Item2)) &&
                    ((invocationArguments == null && kvp.Key.Item3 == null) || invocationArguments.Length == kvp.Key.Item3.Length))
                {
                    bool invocationMatching = true;
                    for (var i = 0; i < invocationArguments.Length && invocationMatching; i++)
                    {
                        invocationMatching &= kvp.Key.Item3[i] == null || kvp.Key.Item3[i].Test(invocationArguments[i]);
                    }
                    if (invocationMatching)
                    {
                        tracker = kvp.Value;
                        break;
                    }
                }
            }

            var returnValue = GetDefaultValue(invocation.Method.ReturnType);

            if (tracker != null)
            {
                // replace smart parameter with their placeholders
                var refReplacementsByIndex = tracker.RefReplacementsByIndex;
                foreach (var kvp in refReplacementsByIndex)
                {
                    invocation.Arguments[kvp.Key] = kvp.Value;
                }
                var currentExecutor = tracker.NextResult();
                while (true)
                {
                    returnValue = currentExecutor.Execute(invocation);
                    if (currentExecutor.IsTerminal)
                    {
                        break;
                    }
                    else
                    {
                        currentExecutor = tracker.NextResult();
                    }
                }

                // replace smart parameters' placeholders with default value, if they're not swapped out
                foreach (var kvp in refReplacementsByIndex)
                {
                    if (ReferenceEquals(invocation.Arguments[kvp.Key], kvp.Value))
                    {
                        var parameterType = invocation.Method.GetParameters()[kvp.Key].ParameterType;
                        // If we have an 'out int', for example, the type is actually a by-ref int&.
                        if (parameterType.IsByRef)
                        {
                            parameterType = parameterType.GetElementType();
                        }
                        if (parameterType.IsValueType)
                        {
                            invocation.Arguments[kvp.Key] = Activator.CreateInstance(parameterType);
                        }
                        else
                        {
                            invocation.Arguments[kvp.Key] = null;
                        }
                    }
                }
            }
            return(returnValue);
        }