/// <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.IsMockable(typeof(TResult)); MethodInfo info; IReadOnlyList <Expression> arguments; if (setup.Body.NodeType == ExpressionType.MemberAccess) { var memberExpr = ((MemberExpression)setup.Body); Guard.NotField(memberExpr); 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.IsMockable(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); }