Example #1
0
		public void Dispose()
		{
			foreach (var invocation in invocations)
			{
				invocation.Dispose();
			}

			current = null;
		}
Example #2
0
		public FluentMockContext()
		{
			current = this;
		}
Example #3
0
		public static IMatcher CreateMatcher(Expression expression, bool isParams)
		{
			// Type inference on the call might 
			// do automatic conversion to the desired 
			// method argument type, and a Convert expression type 
			// might be the topmost instead.
			// i.e.: It.IsInRange(0, 100, Range.Inclusive)
			// the values are ints, but if the method to call 
			// expects, say, a double, a Convert node will be on 
			// the expression.
			if (isParams && (expression.NodeType == ExpressionType.NewArrayInit || !expression.Type.IsArray))
			{
				return new ParamArrayMatcher((NewArrayExpression)expression);
			}

			var originalExpression = expression;
			if (expression.NodeType == ExpressionType.Convert)
			{
				expression = ((UnaryExpression)expression).Operand;
			}

			// SetupSet passes a custom expression.
			var matchExpression = expression as MatchExpression;
			if (matchExpression != null)
			{
				return new Matcher(matchExpression.Match);
			}

			if (expression.NodeType == ExpressionType.Call)
			{
				var call = (MethodCallExpression)expression;

				// Try to determine if invocation is to a matcher.
				using (var context = new FluentMockContext())
				{
					Expression.Lambda<Action>(call).Compile().Invoke();

					if (context.LastMatch != null)
					{
						return new Matcher(context.LastMatch);
					}
				}

				var attr = call.Method.GetCustomAttribute<AdvancedMatcherAttribute>(true);
#pragma warning disable 618
				var staticMatcherMethodAttr = call.Method.GetCustomAttribute<MatcherAttribute>(true);
#pragma warning restore 618

				if (attr != null)
				{
					var matcher = attr.CreateMatcher();
					matcher.Initialize(expression);
					return matcher;
				}
				else if (staticMatcherMethodAttr != null)
				{
					var matcher = new MatcherAttributeMatcher();
					matcher.Initialize(expression);
					return matcher;
				}
				else
				{
					var matcher = new LazyEvalMatcher();
					matcher.Initialize(expression);
					return matcher;
				}
			}
			else if (expression.NodeType == ExpressionType.MemberAccess)
			{
				// Try to determine if invocation is to a matcher.
				using (var context = new FluentMockContext())
				{
					Expression.Lambda<Action>((MemberExpression)expression).Compile().Invoke();
					if (context.LastMatch != null)
					{
						return new Matcher(context.LastMatch);
					}
				}
			}

			// Try reducing locals to get a constant.
			var reduced = originalExpression.PartialEval();
			if (reduced.NodeType == ExpressionType.Constant)
			{
				return new ConstantMatcher(((ConstantExpression)reduced).Value);
			}

			if (reduced.NodeType == ExpressionType.Quote)
			{
				return new ExpressionMatcher(((UnaryExpression)expression).Operand);
			}

			throw new NotSupportedException(
				string.Format(CultureInfo.CurrentCulture, Resources.UnsupportedExpression, expression));
		}
Example #4
0
        private static TCall SetupSetImpl <T, TCall>(
            Mock <T> mock,
            Action <T> setterExpression,
            Func <Mock, LambdaExpression, MethodInfo, Expression[], TCall> callFactory)
            where T : class
            where TCall : MethodCall
        {
            using (var context = new FluentMockContext())
            {
                setterExpression(mock.Object);

                var last = context.LastInvocation;
                if (last == null)
                {
                    throw new ArgumentException(string.Format(
                                                    CultureInfo.InvariantCulture,
                                                    Resources.SetupOnNonVirtualMember,
                                                    string.Empty));
                }

                var setter = last.Invocation.Method;
                if (!setter.IsPropertySetter())
                {
                    throw new ArgumentException(Resources.SetupNotSetter);
                }

                // No need to call ThrowIfCantOverride as non-overridable would have thrown above already.

                // Get the variable name as used in the actual delegate :)
                // because of delegate currying, look at the last parameter for the Action's backing method, not the first
                var setterExpressionParameters = setterExpression.GetMethodInfo().GetParameters();
                var parameterName = setterExpressionParameters[setterExpressionParameters.Length - 1].Name;
                var x             = Expression.Parameter(last.Invocation.Method.DeclaringType, parameterName);

                var arguments  = last.Invocation.Arguments;
                var parameters = setter.GetParameters();
                var values     = new Expression[arguments.Length];

                if (last.Match == null)
                {
                    // Length == 1 || Length == 2 (Indexer property)
                    for (int i = 0; i < arguments.Length; i++)
                    {
                        values[i] = GetValueExpression(arguments[i], parameters[i].ParameterType);
                    }

                    var lambda = Expression.Lambda(
                        typeof(Action <>).MakeGenericType(x.Type),
                        Expression.Call(x, last.Invocation.Method, values),
                        x);

                    return(callFactory(last.Mock, lambda, last.Invocation.Method, values));
                }
                else
                {
                    var matchers     = new Expression[arguments.Length];
                    var valueIndex   = arguments.Length - 1;
                    var propertyType = setter.GetParameters()[valueIndex].ParameterType;

                    // If the value matcher is not equal to the property
                    // type (i.e. prop is int?, but you use It.IsAny<int>())
                    // add a cast.
                    if (last.Match.RenderExpression.Type != propertyType)
                    {
                        values[valueIndex] = Expression.Convert(last.Match.RenderExpression, propertyType);
                    }
                    else
                    {
                        values[valueIndex] = last.Match.RenderExpression;
                    }

                    matchers[valueIndex] = new MatchExpression(last.Match);

                    if (arguments.Length == 2)
                    {
                        // TODO: what about multi-index setters?
                        // Add the index value for the property indexer
                        values[0] = GetValueExpression(arguments[0], parameters[0].ParameterType);
                        // TODO: No matcher supported now for the index
                        matchers[0] = values[0];
                    }

                    var lambda = Expression.Lambda(
                        typeof(Action <>).MakeGenericType(x.Type),
                        Expression.Call(x, last.Invocation.Method, values),
                        x);

                    return(callFactory(last.Mock, lambda, last.Invocation.Method, matchers));
                }
            }
        }
Example #5
0
 public FluentMockContext()
 {
     current = this;
 }
        public static IMatcher CreateMatcher(Expression expression, bool isParams)
        {
            // Type inference on the call might
            // do automatic conversion to the desired
            // method argument type, and a Convert expression type
            // might be the topmost instead.
            // i.e.: It.IsInRange(0, 100, Range.Inclusive)
            // the values are ints, but if the method to call
            // expects, say, a double, a Convert node will be on
            // the expression.
            if (isParams && (expression.NodeType == ExpressionType.NewArrayInit || !expression.Type.IsArray))
            {
                return(new ParamArrayMatcher((NewArrayExpression)expression));
            }

            var originalExpression = expression;

            if (expression.NodeType == ExpressionType.Convert)
            {
                expression = ((UnaryExpression)expression).Operand;
            }

            // SetupSet passes a custom expression.
            var matchExpression = expression as MatchExpression;

            if (matchExpression != null)
            {
                return(new Matcher(matchExpression.Match));
            }

            if (expression.NodeType == ExpressionType.Call)
            {
                var call = (MethodCallExpression)expression;

                // Try to determine if invocation is to a matcher.
                using (var context = new FluentMockContext())
                {
                    Expression.Lambda <Action>(call).Compile().Invoke();

                    if (context.LastMatch != null)
                    {
                        return(new Matcher(context.LastMatch));
                    }
                }

                var attr = call.Method.GetCustomAttribute <AdvancedMatcherAttribute>(true);
#pragma warning disable 618
                var staticMatcherMethodAttr = call.Method.GetCustomAttribute <MatcherAttribute>(true);
#pragma warning restore 618

                if (attr != null)
                {
                    var matcher = attr.CreateMatcher();
                    matcher.Initialize(expression);
                    return(matcher);
                }
                else if (staticMatcherMethodAttr != null)
                {
                    var matcher = new MatcherAttributeMatcher();
                    matcher.Initialize(expression);
                    return(matcher);
                }
                else
                {
                    var matcher = new LazyEvalMatcher();
                    matcher.Initialize(expression);
                    return(matcher);
                }
            }
            else if (expression.NodeType == ExpressionType.MemberAccess)
            {
                // Try to determine if invocation is to a matcher.
                using (var context = new FluentMockContext())
                {
                    Expression.Lambda <Action>((MemberExpression)expression).Compile().Invoke();
                    if (context.LastMatch != null)
                    {
                        return(new Matcher(context.LastMatch));
                    }
                }
            }

            // Try reducing locals to get a constant.
            var reduced = originalExpression.PartialEval();
            if (reduced.NodeType == ExpressionType.Constant)
            {
                return(new ConstantMatcher(((ConstantExpression)reduced).Value));
            }

            if (reduced.NodeType == ExpressionType.Quote)
            {
                return(new ExpressionMatcher(((UnaryExpression)expression).Operand));
            }

            throw new NotSupportedException(
                      string.Format(CultureInfo.CurrentCulture, Resources.UnsupportedExpression, expression));
        }