示例#1
0
        /// <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);
        }