public FormattableString TryGetFriendlyMessage(FailedAssertion assertion) { var notContains = assertion.IsNegated; var callExpression = (MethodCallExpression)assertion.ExpressionWithoutNegation; var instance = callExpression.Object; var isExtensionMethod = callExpression.Method.IsDefined(typeof(ExtensionAttribute), false); if (isExtensionMethod) { instance = callExpression.Arguments.First(); } var expectedContainedValueExpression = callExpression.Arguments.Skip(isExtensionMethod ? 1 : 0).First(); FormattableString expectedValueString; if (ExpressionHelper.IsConstantExpression(expectedContainedValueExpression)) { expectedValueString = $"{expectedContainedValueExpression}"; } else { expectedValueString = $"{expectedContainedValueExpression} (value: {expectedContainedValueExpression.ToValue()})"; } if (instance != null && instance.Type == typeof(string)) { return($"Expected {instance} (value: {instance.ToValue()}) to{(notContains ? " not " : " ")}contain {expectedValueString}."); } return($"Expected {instance} to{(notContains ? " not " : " ")}contain {expectedValueString}."); }
public HandledException?Handle(FailedAssertion assertion) { var nullVisitor = new NullReferenceVisitor(); nullVisitor.Visit(assertion.Expression); if (nullVisitor.CauseOfNullReference != null) { var message = nullVisitor.CauseOfNullReference switch { MemberExpression memberExpression => nullVisitor.ExceptionWasThrownInternally ? GetReasonMessageInternalException(memberExpression) : GetReasonMessage(memberExpression), MethodCallExpression methodCallExpression => nullVisitor.ExceptionWasThrownInternally ? GetReasonMessageInternalException(methodCallExpression) : GetReasonMessage(methodCallExpression), UnaryExpression unaryExpression when unaryExpression.NodeType == ExpressionType.ArrayLength => GetReasonMessage(unaryExpression), BinaryExpression binaryExpression when binaryExpression.NodeType == ExpressionType.ArrayIndex => GetReasonMessage(binaryExpression), _ => null }; if (message != null) { return(new HandledException(message, nullVisitor.CauseOfNullReference)); } } return(null); }
private static bool IsNullEqualityCheck(FailedAssertion failedAssertion) { return((failedAssertion.Expression.NodeType == ExpressionType.Equal || failedAssertion.Expression.NodeType == ExpressionType.NotEqual) && failedAssertion.Expression is BinaryExpression b && ((b.Right is ConstantExpression c && c.Value == null) || (b.Right is DefaultExpression && b.Right.Type.IsClass))); }
public bool IsMatch(FailedAssertion failedAssertion) { return(failedAssertion.Expression is MethodCallExpression methodCallExpression && methodCallExpression.Method.Name == nameof(Enumerable.SequenceEqual) && methodCallExpression.Arguments.Count >= 2 && ExpressionHelper.GetInstanceOfMethodCall(methodCallExpression).Type.IsType <IEnumerable>() && methodCallExpression.Arguments[1].Type.IsType <IEnumerable>()); }
public bool IsMatch(FailedAssertion failedAssertion) { var expression = failedAssertion.Expression; return((EqualityPattern.IsEqualityComparison(expression) || LessThanOrGreaterThanPattern.IsNumericalComparison(expression)) && expression is BinaryExpression binaryExpression && IsLengthAccess(binaryExpression.Left)); }
public FormattableString TryGetFriendlyMessage(FailedAssertion assertion) { var methodCallExpression = (MethodCallExpression)((UnaryExpression)assertion.Expression).Operand; var collectionExpression = ExpressionHelper.GetInstanceOfMethodCall(methodCallExpression); var filter = (LambdaExpression)methodCallExpression.Arguments[1]; return($"Did not expect all items of {collectionExpression} to match the filter {filter.Body}."); }
public FormattableString?TryGetFriendlyMessage(FailedAssertion assertion) { var methodCall = (MethodCallExpression)assertion.ExpressionWithoutNegation; var arg1 = methodCall.Arguments[0]; var arg2 = methodCall.Arguments[1]; var result = assertion.IsNegated ? (FormattableString)$"Expected {arg1} and {arg2} to be a different instances." : $"Expected {arg1} and {arg2} to be the same instance."; return(result); }
public FormattableString TryGetFriendlyMessage(FailedAssertion assertion) { var memberExpression = (MemberExpression)assertion.ExpressionWithoutNegation; if (assertion.IsNegated) { return ($"Expected {memberExpression.Expression} to not have a value but its value was {memberExpression.Expression.ToValue()}."); } return($"Expected {memberExpression.Expression} to have a value."); }
public FormattableString TryGetFriendlyMessage(FailedAssertion assertion) { var notAny = assertion.IsNegated; MethodCallExpression methodCallExpression; if (notAny) { methodCallExpression = (MethodCallExpression)((UnaryExpression)assertion.Expression).Operand; } else { methodCallExpression = (MethodCallExpression)assertion.Expression; } var collection = ExpressionHelper.GetInstanceOfMethodCall(methodCallExpression); FormattableString filterString; if (methodCallExpression.Arguments.Count == 2 && methodCallExpression.Arguments[1] is LambdaExpression lambdaExpression) { filterString = $" that match the filter {lambdaExpression.Body}"; } else { filterString = $""; } string actualCountString = ""; if (notAny) { var actualCount = ExpressionHelper.GetCollectionItemCount(collection, methodCallExpression); actualCountString = $" but it actually contained {actualCount} {(actualCount == 1 ? "item" : "items")}"; } FormattableString result = $"Expected {collection} to {(notAny ? "not " : "")}contain {(notAny ? "any " : "")}items{filterString}{actualCountString}."; if (notAny) { result = $@"{result} Value of {collection}: "; } return(result); }
public HandledException?Handle(FailedAssertion assertion) { var nullVisitor = new ArgumentNullVisitor(); nullVisitor.Visit(assertion.Expression); if (nullVisitor.CauseOfArgumentNull != null) { var message = GetReasonMessage(nullVisitor.CauseOfArgumentNull); return(new HandledException(message, nullVisitor.CauseOfArgumentNull)); } return(null); }
public FormattableString?TryGetFriendlyMessage(FailedAssertion assertion) { var typeAssertion = ((TypeBinaryExpression)assertion.ExpressionWithoutNegation); var result = ExpressionHelper.EvaluateExpression(typeAssertion.Expression); var expectedType = TypeHelper.TypeNameToString(typeAssertion.TypeOperand); if (result == null) { return($"Expected {typeAssertion.Expression} to be of type {expectedType} but it was null."); } return(!assertion.IsNegated ? $"Expected {typeAssertion.Expression} to be of type {expectedType} but its actual type was {TypeHelper.TypeNameToString(result.GetType())}." : (FormattableString)$"Expected {typeAssertion.Expression} to not be of type {expectedType}."); }
public FormattableString TryGetFriendlyMessage(FailedAssertion assertion) { var left = EqualityPattern.GetLeftSide(assertion.Expression); var right = EqualityPattern.GetRightSide(assertion.Expression, left); if (right.NodeType == ExpressionType.Convert && right.Type == typeof(object)) { right = ((UnaryExpression)right).Operand; } if (IsConstantExpression(right)) { return($"Expected {left} to equal {right} but {left} was {left.ToValue()}."); } return($"Expected {left} to equal {right} but {left} was {left.ToValue()} while {right} was {right.ToValue()}."); }
public FormattableString?TryGetFriendlyMessage(FailedAssertion assertion) { bool expectedNull = false; Expression?expression = null; if (assertion.Expression is BinaryExpression b) { if (b.NodeType == ExpressionType.Equal) { expectedNull = true; } expression = b.Left; } else if (assertion.ExpressionWithoutNegation is TypeBinaryExpression typeIsExpression) { if (assertion.IsNegated) { expectedNull = true; } expression = typeIsExpression.Expression; } if (expression != null) { if (expectedNull) { return($"Expected {expression} to be null but it was {expression.ToValue()} instead."); } else { return($"Expected {expression} to not be null."); } } return(default);
public HandledException?Handle(FailedAssertion assertion) { var visitor = new IndexOutOfRangeExceptionVisitor(); visitor.Visit(assertion.Expression); var causeOfException = visitor.CauseOfIndexOutOfRangeException; if (causeOfException == null) { return(null); } Expression indexExpression; Expression operand; int? actualLength; string lengthString; if (causeOfException.NodeType == ExpressionType.ArrayIndex && assertion.Exception is IndexOutOfRangeException) { var b = (BinaryExpression)causeOfException; indexExpression = b.Right; operand = b.Left; actualLength = (int?)ExpressionHelper.EvaluateExpression(Expression.ArrayLength(operand)); lengthString = "length"; } else if (assertion.Exception is ArgumentOutOfRangeException && causeOfException is MethodCallExpression methodCallExpression && methodCallExpression.Method.Name == "get_Item" && methodCallExpression.Arguments.Count == 1) { indexExpression = methodCallExpression.Arguments[0]; operand = methodCallExpression.Object; actualLength = ExpressionHelper.GetCollectionItemCount(operand); lengthString = "count"; }
public FormattableString TryGetFriendlyMessage(FailedAssertion assertion) { var startsWith = IsStartsOrEndsWithCall(assertion.Expression); var methodCallExpression = (MethodCallExpression)assertion.ExpressionWithoutNegation; var method = methodCallExpression.Method.Name == nameof(string.StartsWith) ? "start with" : "end with"; var arg = methodCallExpression.Arguments[0]; var instance = GetInstanceOfMethodCall(methodCallExpression); if (IsConstantExpression(arg)) { return($@"Expected {instance} to{(startsWith ? " " : " not ")}{method} {arg}. Value of {instance}: {instance.ToValue()}"); } return($@"Expected {instance} to{(startsWith ? " " : " not ")}{method} {arg} (value: {arg.ToValue()}). Value of {instance}: {instance.ToValue()}"); }
public HandledException?Handle(FailedAssertion assertion) { var linqVisitor = new LinqElementCountVisitor(); linqVisitor.Visit(assertion.Expression); if (linqVisitor.CauseOfLinqException != null) { var filtered = linqVisitor.CauseOfLinqException.Arguments.Count == 2 && linqVisitor.CauseOfLinqException.Arguments[1] is LambdaExpression; var instanceOfMethodCallExpression = ExpressionHelper.GetInstanceOfMethodCall(linqVisitor.CauseOfLinqException); var message = GetReasonMessage(linqVisitor.CauseOfLinqException, linqVisitor.Error, linqVisitor.ActualCount, filtered, instanceOfMethodCallExpression); if ((linqVisitor.Error == LinqElementCountErrorTypes.TooFew && filtered) || linqVisitor.Error == LinqElementCountErrorTypes.TooMany) { var filter = filtered && linqVisitor.Error == LinqElementCountErrorTypes.TooMany ? (LambdaExpression)linqVisitor.CauseOfLinqException.Arguments[1] : null; var items = GetItems(filter, linqVisitor.CauseOfLinqException, instanceOfMethodCallExpression); if (items != null) { message = $@"{message} Value of {(filter != null ? linqVisitor.CauseOfLinqException : instanceOfMethodCallExpression)}: {Serializer.Serialize(items)}"; } } return(new HandledException(message, linqVisitor.CauseOfLinqException)); } return(null); }
public FormattableString?TryGetFriendlyMessage(FailedAssertion assertion) { return(null); }
public bool IsMatch(FailedAssertion failedAssertion) { return(IsAllMethodCall(failedAssertion.Expression)); }
public FormattableString TryGetFriendlyMessage(FailedAssertion assertion) { var methodCallExpression = (MethodCallExpression)assertion.Expression; var collectionExpression = ExpressionHelper.GetInstanceOfMethodCall(methodCallExpression); var filter = (LambdaExpression)methodCallExpression.Arguments[1]; var collection = ((IEnumerable)ExpressionHelper.EvaluateExpression(collectionExpression) !).Cast <object>(); var compiledFilter = filter.Compile(true); var invalidMatches = new List <object>(); var moreItems = false; var invalidCount = 0; var subMessages = new List <FormattableString>(); var index = 0; foreach (var obj in collection) { var isMatch = (bool)compiledFilter.DynamicInvoke(obj); if (!isMatch) { invalidCount++; if (invalidMatches.Count == 10) { moreItems = true; } else { invalidMatches.Add(obj); var namedConstant = new NamedConstantExpression("item", obj); var newExpression = Expression.Lambda <Func <bool> >( ExpressionHelper.ReplaceParameter(filter.Body, filter.Parameters[0], namedConstant)); var analyzer = new AssertionFailureAnalyzer(new AssertionFailureContext(new Assertion(newExpression, null, null), null)); var failures = analyzer.AnalyzeAssertionFailures(); foreach (var failure in failures) { if (failure.Message != null) { subMessages.Add(collectionExpression is MethodCallExpression ? $"[{index}] - {failure.Message}" : (FormattableString)$"{collectionExpression}[{index}] - {failure.Message}"); } } } } index++; } FormattableString MessagesPerItem() { return(subMessages.Count switch { 0 => $"", 1 when invalidCount == 1 => $@" {subMessages[0]}", _ => $@" Messages per item: {subMessages}" }); }
public bool IsMatch(FailedAssertion failedAssertion) { return(IsEqualityComparison(failedAssertion.Expression)); }
public bool IsMatch(FailedAssertion failedAssertion) { return(failedAssertion.Expression.NodeType == ExpressionType.Equal || EqualityPattern.EqualsMethodShouldBeTrue(failedAssertion.Expression)); }
public bool IsMatch(FailedAssertion failedAssertion) { return(IsNullEqualityCheck(failedAssertion) || IsObjectCheck(failedAssertion)); }
private static bool IsObjectCheck(FailedAssertion failedAssertion) { return(failedAssertion.ExpressionWithoutNegation is TypeBinaryExpression t && t.NodeType == ExpressionType.TypeIs && t.TypeOperand == typeof(object)); }
public bool IsMatch(FailedAssertion failedAssertion) { return(IsStartsOrEndsWithCall(failedAssertion.ExpressionWithoutNegation)); }
public bool IsMatch(FailedAssertion failedAssertion) { return(failedAssertion.ExpressionWithoutNegation is TypeBinaryExpression t && t.NodeType == ExpressionType.TypeIs && t.TypeOperand != typeof(object)); }
public bool IsMatch(FailedAssertion failedAssertion) { return(failedAssertion.ExpressionWithoutNegation is MemberExpression); }
public bool IsMatch(FailedAssertion failedAssertion) { return(true); }
public bool IsMatch(FailedAssertion failedAssertion) { return(IsAnyMethodCall(failedAssertion.ExpressionWithoutNegation)); }
public bool IsMatch(FailedAssertion failedAssertion) { return(IsHasValueAccess(failedAssertion.ExpressionWithoutNegation)); }
public FormattableString?TryGetFriendlyMessage(FailedAssertion assertion) { var methodCallExpression = (MethodCallExpression)assertion.Expression; var collection1Expression = ExpressionHelper.GetInstanceOfMethodCall(methodCallExpression); var collection2Expression = methodCallExpression.Arguments[1]; var collection1 = ((IEnumerable)ExpressionHelper.EvaluateExpression(collection1Expression) !).Cast <object>(); var collection2 = ((IEnumerable)ExpressionHelper.EvaluateExpression(collection2Expression) !).Cast <object>(); var differences = new List <Difference>(); var enumerableType = TypeHelper.GetTypeInsideEnumerable(collection1Expression.Type); if (enumerableType == null) { return(null); } var equals = GetComparerFunc(methodCallExpression, enumerableType); FormattableString result; if (equals != null) { var index = 0; var hasMoreDifferences = false; var differenceCount = 0; IEnumerator <object>?enumerator1 = null; IEnumerator <object>?enumerator2 = null; try { enumerator1 = collection1.GetEnumerator(); enumerator2 = collection2.GetEnumerator(); while (true) { var moveNext1 = enumerator1.MoveNext(); var moveNext2 = enumerator2.MoveNext(); if (!moveNext1 && !moveNext2) { break; } var current1 = moveNext1 ? enumerator1.Current : null; var current2 = moveNext2 ? enumerator2.Current : null; if (!equals(current1, current2)) { differenceCount++; if (differences.Count == 10) { hasMoreDifferences = true; } else { differences.Add(new Difference() { Index = index, ValueSequence1 = current1, HasValueSequence1 = moveNext1, ValueSequence2 = current2, HasValueSequence2 = moveNext2 }); } } index++; } } finally { enumerator1?.Dispose(); enumerator2?.Dispose(); } var differencesString = differences.Select(d => $"[{d.Index}]: {(d.HasValueSequence1 ? Serializer.Serialize(d.ValueSequence1) ?? "null" : "(no value)")} <> {(d.HasValueSequence2 ? Serializer.Serialize(d.ValueSequence2) ?? "null" : "(no value)")}") .ToList(); result = $@"Expected {collection1Expression} to be equal to {collection2Expression}, but there {(differenceCount > 1 ? $"were {differenceCount} differences" : "was 1 difference")}{(hasMoreDifferences ? " (first 10)" : "")}: {string.Join("," + Environment.NewLine, differencesString)}"; } else { result = $@"Expected {collection1Expression} to be equal to {collection2Expression} but they were not."; } return($@"{result} Value of {collection1Expression}: {collection1} Value of {collection2Expression}: {collection2}"); }