public static Mock <TResult> FluentMock <T, TResult>(this Mock <T> mock, Expression <Func <T, TResult> > setup) where T : class where TResult : class { Guard.NotNull(mock, nameof(mock)); Guard.NotNull(setup, nameof(setup)); Guard.Mockable(typeof(TResult)); MethodInfo info; if (setup.Body.NodeType == ExpressionType.MemberAccess) { var memberExpr = ((MemberExpression)setup.Body); memberExpr.ThrowIfNotMockeable(); info = ((PropertyInfo)memberExpr.Member).GetGetMethod(); } else if (setup.Body.NodeType == ExpressionType.Call) { info = ((MethodCallExpression)setup.Body).Method; } else { throw new NotSupportedException(string.Format(Resources.UnsupportedExpression, setup.ToStringFixed())); } Guard.Mockable(info.ReturnType); Mock fluentMock; MockWithWrappedMockObject innerMock; if (mock.InnerMocks.TryGetValue(info, out innerMock)) { fluentMock = innerMock.Mock; } else { fluentMock = ((IMocked)mock.GetDefaultValue(info, useAlternateProvider: DefaultValueProvider.Mock)).Mock; Mock.SetupAllProperties(fluentMock); innerMock = new MockWithWrappedMockObject(fluentMock, fluentMock.Object); // ^^^^^^^^^^^^^^^^^ // NOTE: Above, we are assuming that a default value was returned that is neither a `Task<T>` nor a `ValueTask<T>`, // i.e. nothing we'd need to first "unwrap" to get at the actual mocked object. This assumption would seem permissible // since the present method gets called only for multi-dot expressions ("recursive mocking"), which do not allow // `await` expressions. Therefore we don't need to deal with `Task<T>` nor `ValueTask<T>`, and we proceed as if the // returned default value were already "unwrapped". } var result = (TResult)innerMock.WrappedMockObject; mock.Setup(setup).Returns(result); return((Mock <TResult>)fluentMock); }
/// <summary> /// Retrieves a fluent mock from the given setup expression. /// </summary> private static Mock <TResult> FluentMock <T, TResult>(Mock <T> mock, Expression <Func <T, TResult> > setup) where T : class where TResult : class { Guard.NotNull(mock, nameof(mock)); Guard.NotNull(setup, nameof(setup)); Guard.Mockable(typeof(TResult)); MethodInfo info; IReadOnlyList <Expression> arguments; if (setup.Body.NodeType == ExpressionType.MemberAccess) { var memberExpr = ((MemberExpression)setup.Body); memberExpr.ThrowIfNotMockeable(); info = ((PropertyInfo)memberExpr.Member).GetGetMethod(); arguments = new Expression[0]; } else if (setup.Body.NodeType == ExpressionType.Call) { var callExpr = (MethodCallExpression)setup.Body; info = callExpr.Method; arguments = callExpr.Arguments; } else { throw new NotSupportedException(string.Format(Resources.UnsupportedExpression, setup.ToStringFixed())); } Guard.Mockable(info.ReturnType); Mock fluentMock; object result; if (mock.Setups.GetInnerMockSetups().TryFind(new InvocationShape(setup, info, arguments), out var inner)) { Debug.Assert(inner.TryGetReturnValue(out _)); // guaranteed by .GetInnerMockSetups() fluentMock = inner.GetInnerMock(); _ = inner.TryGetReturnValue(out result); } else { result = mock.GetDefaultValue(info, out fluentMock, useAlternateProvider: DefaultValueProvider.Mock); Debug.Assert(fluentMock != null); Mock.SetupAllProperties(fluentMock); } mock.AddInnerMockSetup(info, arguments, setup, result); return((Mock <TResult>)fluentMock); }
private MethodInfo GetTargetMethod(Type objectType, Type returnType) { // dte.Solution => if (this.setupRightmost && this.isAtRightmost) { //.Setup(mock => mock.Solution) return(typeof(Mock <>) .MakeGenericType(objectType) .GetMethods("Setup") .First(m => m.IsGenericMethod) .MakeGenericMethod(returnType)); } else { //.FluentMock(mock => mock.Solution) Guard.Mockable(returnType); return(FluentMockMethod.MakeGenericMethod(objectType, returnType)); } }
public Mock(MockBehavior behavior, params object[] args) { Guard.Mockable(typeof(T)); if (args == null) { args = new object[] { null }; } this.additionalInterfaces = new List <Type>(); this.behavior = behavior; this.configuredDefaultValues = new Dictionary <Type, object>(); this.constructorArguments = args; this.defaultValueProvider = DefaultValueProvider.Empty; this.eventHandlers = new EventHandlerCollection(); this.invocations = new InvocationCollection(); this.name = CreateUniqueDefaultMockName(); this.setups = new SetupCollection(); this.switches = Switches.Default; this.CheckParameters(); }
private static MethodInfo GetTargetMethod(Type objectType, Type returnType) { Guard.Mockable(returnType); return(FluentMockGenericMethod.MakeGenericMethod(objectType, returnType)); }