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); }
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); }
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); }
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); }
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()); } } }
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); } } }
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); }
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); }
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); }