/// <summary> /// Invokes the given delegate when the setup method is invoked, typically used /// to access and set ref/out arguments in a typed fashion. Used in combination /// with <see cref="SetupExtension.Setup{TDelegate}(object, TDelegate)"/>. /// </summary> /// <typeparam name="TDelegate">The lambda to invoke when the setup method runs.</typeparam> /// <param name="target">The setup being performed.</param> /// <param name="handler">The lambda to invoke when the setup is matched.</param> public static void Returns <TDelegate>(this ISetup <TDelegate> target, TDelegate handler) { using (new SetupScope()) { var @delegate = handler as Delegate; // Simulate Any<T> matchers for each member parameter var parameters = @delegate.Method.GetParameters(); var arguments = new object[parameters.Length]; var defaultValue = new DefaultValue(false); for (var i = 0; i < arguments.Length; i++) { var parameter = parameters[i]; MockSetup.Push(new AnyMatcher(parameter.IsOut ? parameter.ParameterType.GetElementType() : parameter.ParameterType)); if (!parameter.IsOut) { arguments[i] = defaultValue.For(parameter.ParameterType); } } target.Delegate.DynamicInvoke(arguments); // Now we'd have a setup in place and an actual invocation. var setup = MockContext.CurrentSetup; if (setup != null) { setup.Invocation.Target .GetMock() .GetPipeline(setup) .Behaviors.Add(new ReturnsDelegateBehavior(@delegate)); } } }
/// <summary> /// Invokes the given delegate when the method being set up is invoked, typically used /// to access and set ref/out arguments in a typed fashion. Used in combination /// with <see cref="SetupExtension.Setup{TDelegate}(object, TDelegate)"/>. /// </summary> /// <typeparam name="TDelegate">The lambda to invoke when the setup method runs.</typeparam> /// <param name="target">The setup being performed.</param> /// <param name="handler">The lambda to invoke when the setup is matched.</param> public static void Returns <TDelegate>(this ISetup <TDelegate> target, TDelegate handler) { if (handler is not Delegate @delegate) { throw new ArgumentException(ThisAssembly.Strings.Returns.DelegateExpected, nameof(handler)); } using (new SetupScope()) { // Simulate Any<T> matchers for each member parameter var parameters = @delegate.Method.GetParameters(); object?[] arguments = new object[parameters.Length]; var defaultValue = new DefaultValueProvider(false); for (var i = 0; i < arguments.Length; i++) { var parameter = parameters[i]; MockSetup.Push(new AnyMatcher(parameter.IsOut ? parameter.ParameterType.GetElementType() : parameter.ParameterType)); if (!parameter.IsOut) { arguments[i] = defaultValue.GetDefault(parameter.ParameterType); } } target.Delegate.DynamicInvoke(arguments); // Now we'd have a setup in place and an actual invocation. var setup = MockContext.CurrentSetup; if (setup != null) { setup.Invocation.Target .AsMock() .GetPipeline(setup) .Behaviors.Add(new ReturnsDelegateBehavior(@delegate)); } } }
/// <summary> /// Matches any value that is not equal to the provided constant value. /// </summary> /// <typeparam name="T">The type of the argument.</typeparam> public static T Not <T>(T value) => MockSetup.Push <T>(new NotMatcher <T>(value));
/// <summary> /// Matches a value of the given type if it satisfies the specified condition. /// </summary> /// <typeparam name="T">The type of the argument.</typeparam> /// <param name="condition">The condition to check against actual invocation values.</param> public static T Any <T>(Func <T, bool> condition) => MockSetup.Push <T>(new ConditionalMatcher <T>(condition));
/// <summary> /// Matches any value of the given type. /// </summary> /// <typeparam name="T">The type of the argument.</typeparam> public static T Any <T>() => MockSetup.Push <T>(AnyMatcher <T> .Default);