Beispiel #1
0
        public override InterceptionAction Handle(Invocation invocation, Mock mock)
        {
            Debug.Assert(invocation.Method != null);
            Debug.Assert(invocation.Method.ReturnType != null);

            var method = invocation.Method;

            if (mock.CallBase)
            {
                var declaringType = method.DeclaringType;
                if (declaringType.GetTypeInfo().IsInterface)
                {
                    if (mock.TargetType.GetTypeInfo().IsInterface)
                    {
                        // Case 1: Interface method of an interface proxy.
                        // There is no base method to call, so fall through.
                    }
                    else
                    {
                        Debug.Assert(mock.TargetType.GetTypeInfo().IsClass);
                        Debug.Assert(mock.ImplementsInterface(declaringType));

                        // Case 2: Explicitly implemented interface method of a class proxy.
                        // Only call base method if it isn't an event accessor.
                        if (!method.LooksLikeEventAttach() && !method.LooksLikeEventDetach())
                        {
                            invocation.ReturnBase();
                            return(InterceptionAction.Stop);
                        }
                    }
                }
                else
                {
                    Debug.Assert(declaringType.GetTypeInfo().IsClass);

                    // Case 3: Non-interface method of a class proxy.
                    // Only call base method if it isn't abstract.
                    if (!method.IsAbstract)
                    {
                        invocation.ReturnBase();
                        return(InterceptionAction.Stop);
                    }
                }
            }

            if (method.ReturnType == typeof(void))
            {
                invocation.Return();
            }
            else if (mock.InnerMocks.TryGetValue(method, out var inner))
            {
                invocation.Return(inner.WrappedMockObject);
            }
            else
            {
                invocation.Return(mock.GetDefaultValue(method));
            }

            return(InterceptionAction.Stop);
        }
Beispiel #2
0
        public override InterceptionAction Handle(Invocation invocation, Mock mock)
        {
            var methodName = invocation.Method.Name;

            // Special case for event accessors. The following, seemingly random character checks are guards against
            // more expensive checks (for the common case where the invoked method is *not* an event accessor).
            if (methodName.Length > 4)
            {
                if (methodName[0] == 'a' && methodName[3] == '_' && invocation.Method.LooksLikeEventAttach())
                {
                    var eventInfo = GetEventFromName(invocation.Method.Name.Substring("add_".Length), mock);
                    if (eventInfo != null)
                    {
                        // TODO: We could compare `invocation.Method` and `eventInfo.GetAddMethod()` here.
                        // If they are equal, then `invocation.Method` is definitely an event `add` accessor.
                        // Not sure whether this would work with F# and COM; see commit 44070a9.

                        if (mock.CallBase && !invocation.Method.IsAbstract)
                        {
                            invocation.ReturnBase();
                            return(InterceptionAction.Stop);
                        }
                        else if (invocation.Arguments.Length > 0 && invocation.Arguments[0] is Delegate delegateInstance)
                        {
                            mock.EventHandlers.Add(eventInfo.Name, delegateInstance);
                            invocation.Return();
                            return(InterceptionAction.Stop);
                        }
                    }
                }
                else if (methodName[0] == 'r' && methodName.Length > 7 && methodName[6] == '_' && invocation.Method.LooksLikeEventDetach())
                {
                    var eventInfo = GetEventFromName(invocation.Method.Name.Substring("remove_".Length), mock);
                    if (eventInfo != null)
                    {
                        // TODO: We could compare `invocation.Method` and `eventInfo.GetRemoveMethod()` here.
                        // If they are equal, then `invocation.Method` is definitely an event `remove` accessor.
                        // Not sure whether this would work with F# and COM; see commit 44070a9.

                        if (mock.CallBase && !invocation.Method.IsAbstract)
                        {
                            invocation.ReturnBase();
                            return(InterceptionAction.Stop);
                        }
                        else if (invocation.Arguments.Length > 0 && invocation.Arguments[0] is Delegate delegateInstance)
                        {
                            mock.EventHandlers.Remove(eventInfo.Name, delegateInstance);
                            invocation.Return();
                            return(InterceptionAction.Stop);
                        }
                    }
                }
            }

            // Save to support Verify[expression] pattern.
            mock.MutableInvocations.Add(invocation);
            return(InterceptionAction.Continue);
        }
Beispiel #3
0
        public override void Execute(Invocation invocation)
        {
            base.Execute(invocation);

            if (this.returnValueKind == ReturnValueKind.CallBase)
            {
                invocation.ReturnBase();
            }
            else if (this.valueDel != null)
            {
                invocation.Return(this.valueDel.HasCompatibleParameterList(new ParameterInfo[0])
                                        ? valueDel.InvokePreserveStack()                       //we need this, for the user to be able to use parameterless methods
                                        : valueDel.InvokePreserveStack(invocation.Arguments)); //will throw if parameters mismatch
            }
            else if (this.Mock.Behavior == MockBehavior.Strict)
            {
                throw MockException.ReturnValueRequired(invocation);
            }
            else
            {
                invocation.Return(this.ReturnType.GetDefaultValue());
            }

            this.afterReturnCallback?.Invoke(invocation.Arguments);
        }
Beispiel #4
0
        public override InterceptionAction Handle(Invocation invocation, Mock mock)
        {
            Debug.Assert(invocation.Method != null);
            Debug.Assert(invocation.Method.ReturnType != null);

            var method = invocation.Method;

            if (mock.CallBase && !method.IsAbstract)
            {
                invocation.ReturnBase();
            }
            else if (method.ReturnType == typeof(void))
            {
                invocation.Return();
            }
            else if (mock.InnerMocks.TryGetValue(method, out var inner))
            {
                invocation.Return(inner.WrappedMockObject);
            }
            else
            {
                invocation.Return(mock.GetDefaultValue(method));
            }

            return(InterceptionAction.Stop);
        }
Beispiel #5
0
        public override void Execute(Invocation invocation)
        {
            this.invoked = true;

            if (this.responses.TryDequeue(out var response))
            {
                var(kind, arg) = response;
                switch (kind)
                {
                case ResponseKind.Pass:
                    invocation.Return();
                    break;

                case ResponseKind.CallBase:
                    invocation.ReturnBase();
                    break;

                case ResponseKind.Returns:
                    invocation.Return(arg);
                    break;

                case ResponseKind.Throws:
                    throw (Exception)arg;

                case ResponseKind.InvokeFunc:
                    invocation.Return(((Func <object>)arg)());
                    break;
                }
            }
            else
            {
                // we get here if there are more invocations than configured responses.
                // if the setup method does not have a return value, we don't need to do anything;
                // if it does have a return value, we produce the default value.

                var returnType = invocation.Method.ReturnType;
                if (returnType == typeof(void))
                {
                }
                else
                {
                    invocation.Return(returnType.GetDefaultValue());
                }
            }
        }
Beispiel #6
0
        public override void Execute(Invocation invocation)
        {
            base.Execute(invocation);

            if (this.responses.TryDequeue(out Tuple <ResponseKind, object> response))
            {
                switch (response.Item1)
                {
                case ResponseKind.Pass:
                    invocation.Return();
                    break;

                case ResponseKind.CallBase:
                    invocation.ReturnBase();
                    break;

                case ResponseKind.Returns:
                    invocation.Return(response.Item2);
                    break;

                case ResponseKind.Throws:
                    throw (Exception)response.Item2;
                }
            }
            else
            {
                // we get here if there are more invocations than configured responses.
                // if the setup method does not have a return value, we don't need to do anything;
                // if it does have a return value, we produce the default value.

                var returnType = invocation.Method.ReturnType;
                if (returnType == typeof(void))
                {
                }
                else
                {
                    invocation.Return(returnType.GetTypeInfo().IsValueType ? Activator.CreateInstance(returnType)
                                                                                               : null);
                }
            }
        }
Beispiel #7
0
        public override InterceptionAction Handle(Invocation invocation, Mock mock)
        {
            Debug.Assert(invocation.Method != null);
            Debug.Assert(invocation.Method.ReturnType != null);

            var method = invocation.Method;

            if (mock.CallBase)
            {
                var declaringType = method.DeclaringType;
                if (declaringType.IsInterface)
                {
                    if (mock.TargetType.IsInterface)
                    {
                        // Case 1: Interface method of an interface proxy.
                        // There is no base method to call, so fall through.
                    }
                    else
                    {
                        Debug.Assert(mock.TargetType.IsClass);
                        Debug.Assert(mock.ImplementsInterface(declaringType));

                        // Case 2: Explicitly implemented interface method of a class proxy.

                        if (mock.InheritedInterfaces.Contains(declaringType))
                        {
                            // Case 2a: Re-implemented interface.
                            // The base class has its own implementation. Only call base method if it isn't an event accessor.
                            if (!method.LooksLikeEventAttach() && !method.LooksLikeEventDetach())
                            {
                                invocation.ReturnBase();
                                return(InterceptionAction.Stop);
                            }
                        }
                        else
                        {
                            Debug.Assert(mock.AdditionalInterfaces.Contains(declaringType));

                            // Case 2b: Additional interface.
                            // There is no base method to call, so fall through.
                        }
                    }
                }
                else
                {
                    Debug.Assert(declaringType.IsClass);

                    // Case 3: Non-interface method of a class proxy.
                    // Only call base method if it isn't abstract.
                    if (!method.IsAbstract)
                    {
                        invocation.ReturnBase();
                        return(InterceptionAction.Stop);
                    }
                }
            }

            if (method.ReturnType == typeof(void))
            {
                invocation.Return();
            }
            else
            {
                var returnValue = mock.GetDefaultValue(method, out var innerMock);
                if (innerMock != null)
                {
                    mock.AddInnerMockSetup(invocation, returnValue);
                }
                invocation.Return(returnValue);
            }

            return(InterceptionAction.Stop);
        }
Beispiel #8
0
        public static bool Handle(Invocation invocation, Mock mock)
        {
            const BindingFlags bindingFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly;

            var methodName = invocation.Method.Name;

            // Special case for event accessors. The following, seemingly random character checks are guards against
            // more expensive checks (for the common case where the invoked method is *not* an event accessor).
            if (methodName.Length > 4)
            {
                if (methodName[0] == 'a' && methodName[3] == '_' && invocation.Method.IsEventAddAccessor())
                {
                    var implementingMethod = invocation.Method.GetImplementingMethod(invocation.ProxyType);
                    var @event             = implementingMethod.DeclaringType.GetEvents(bindingFlags).SingleOrDefault(e => e.GetAddMethod(true) == implementingMethod);
                    if (@event != null)
                    {
                        bool doesntHaveEventSetup = !mock.MutableSetups.HasEventSetup;

                        if (mock.CallBase && !invocation.Method.IsAbstract)
                        {
                            if (doesntHaveEventSetup)
                            {
                                invocation.ReturnBase();
                            }
                        }
                        else if (invocation.Arguments.Length > 0 && invocation.Arguments[0] is Delegate delegateInstance)
                        {
                            mock.EventHandlers.Add(@event, delegateInstance);

                            if (doesntHaveEventSetup)
                            {
                                invocation.Return();
                            }
                        }

                        return(doesntHaveEventSetup);
                    }
                }
                else if (methodName[0] == 'r' && methodName.Length > 7 && methodName[6] == '_' && invocation.Method.IsEventRemoveAccessor())
                {
                    var implementingMethod = invocation.Method.GetImplementingMethod(invocation.ProxyType);
                    var @event             = implementingMethod.DeclaringType.GetEvents(bindingFlags).SingleOrDefault(e => e.GetRemoveMethod(true) == implementingMethod);
                    if (@event != null)
                    {
                        bool doesntHaveEventSetup = !mock.MutableSetups.HasEventSetup;

                        if (mock.CallBase && !invocation.Method.IsAbstract)
                        {
                            if (doesntHaveEventSetup)
                            {
                                invocation.ReturnBase();
                            }
                        }
                        else if (invocation.Arguments.Length > 0 && invocation.Arguments[0] is Delegate delegateInstance)
                        {
                            mock.EventHandlers.Remove(@event, delegateInstance);

                            if (doesntHaveEventSetup)
                            {
                                invocation.Return();
                            }
                        }

                        return(doesntHaveEventSetup);
                    }
                }
            }

            return(false);
        }
Beispiel #9
0
        public static bool Handle(Invocation invocation, Mock mock)
        {
            var methodName = invocation.Method.Name;

            // Special case for event accessors. The following, seemingly random character checks are guards against
            // more expensive checks (for the common case where the invoked method is *not* an event accessor).
            if (methodName.Length > 4)
            {
                if (methodName[0] == 'a' && methodName[3] == '_' && invocation.Method.IsEventAddAccessor())
                {
                    var eventInfo = GetEventFromName(invocation.Method.Name.Substring("add_".Length), mock);
                    if (eventInfo != null)
                    {
                        // TODO: We could compare `invocation.Method` and `eventInfo.GetAddMethod()` here.
                        // If they are equal, then `invocation.Method` is definitely an event `add` accessor.
                        // Not sure whether this would work with F# and COM; see commit 44070a9.

                        bool doesntHaveEventSetup = !mock.Setups.HasEventSetup;

                        if (mock.CallBase && !invocation.Method.IsAbstract)
                        {
                            if (doesntHaveEventSetup)
                            {
                                invocation.ReturnBase();
                            }
                        }
                        else if (invocation.Arguments.Length > 0 && invocation.Arguments[0] is Delegate delegateInstance)
                        {
                            mock.EventHandlers.Add(eventInfo.Name, delegateInstance);

                            if (doesntHaveEventSetup)
                            {
                                invocation.Return();
                            }
                        }

                        return(doesntHaveEventSetup);
                    }
                }
                else if (methodName[0] == 'r' && methodName.Length > 7 && methodName[6] == '_' && invocation.Method.IsEventRemoveAccessor())
                {
                    var eventInfo = GetEventFromName(invocation.Method.Name.Substring("remove_".Length), mock);
                    if (eventInfo != null)
                    {
                        // TODO: We could compare `invocation.Method` and `eventInfo.GetRemoveMethod()` here.
                        // If they are equal, then `invocation.Method` is definitely an event `remove` accessor.
                        // Not sure whether this would work with F# and COM; see commit 44070a9.

                        bool doesntHaveEventSetup = !mock.Setups.HasEventSetup;

                        if (mock.CallBase && !invocation.Method.IsAbstract)
                        {
                            if (doesntHaveEventSetup)
                            {
                                invocation.ReturnBase();
                            }
                        }
                        else if (invocation.Arguments.Length > 0 && invocation.Arguments[0] is Delegate delegateInstance)
                        {
                            mock.EventHandlers.Remove(eventInfo.Name, delegateInstance);

                            if (doesntHaveEventSetup)
                            {
                                invocation.Return();
                            }
                        }

                        return(doesntHaveEventSetup);
                    }
                }
            }

            return(false);
        }