/// <summary> /// Specifies another verification. /// </summary> /// <param name="assertionTracker">The assertion tracker.</param> /// <returns> /// The assertion tracker. /// </returns> public static AssertionTracker And( [ValidatedNotNull] this AssertionTracker assertionTracker) { assertionTracker.ThrowImproperUseOfFrameworkIfDetected(AssertionTrackerShould.Exist, AssertionTrackerShould.BeMusted, AssertionTrackerShould.BeVerifiedAtLeastOnce); return(assertionTracker); }
/// <summary> /// Specifies that the verifications should be applied /// to the elements of the <see cref="IEnumerable"/> subject. /// </summary> /// <param name="assertionTracker">The assertion tracker.</param> /// <returns> /// The assertion tracker in a state where verifications will be /// applied to the elements of the <see cref="IEnumerable"/> subject. /// </returns> public static AssertionTracker Each( [ValidatedNotNull] this AssertionTracker assertionTracker) { assertionTracker.ThrowImproperUseOfFrameworkIfDetected(AssertionTrackerShould.Exist, AssertionTrackerShould.BeMusted, AssertionTrackerShould.NotBeEached); assertionTracker.Actions |= Actions.Eached; return(assertionTracker); }
private static Exception BuildException( AssertionTracker assertionTracker, Verification verification, string exceptionMessage, ArgumentExceptionKind argumentExceptionKind) { Exception result; switch (assertionTracker.AssertionKind) { case AssertionKind.Unknown: result = new AssertionVerificationFailedException(exceptionMessage); break; case AssertionKind.Argument: switch (argumentExceptionKind) { case ArgumentExceptionKind.ArgumentException: result = new ArgumentException(exceptionMessage); break; case ArgumentExceptionKind.ArgumentNullException: result = new ArgumentNullException(null, exceptionMessage); break; case ArgumentExceptionKind.ArgumentOutOfRangeException: result = new ArgumentOutOfRangeException(exceptionMessage, (Exception)null); break; default: throw new NotSupportedException(Invariant($"This {nameof(ArgumentExceptionKind)} is not supported: {argumentExceptionKind}.")); } break; case AssertionKind.Operation: result = new InvalidOperationException(exceptionMessage); break; case AssertionKind.Test: result = new TestAssertionVerificationFailedException(exceptionMessage); break; default: throw new NotSupportedException(Invariant($"This {nameof(AssertionKind)} is not supported: {assertionTracker.AssertionKind}.")); } result.AddData(verification.Data); return(result); }
private static string BuildVerificationFailedExceptionMessage( AssertionTracker assertionTracker, Verification verification, VerifiableItem verifiableItem, string exceptionMessageSuffix, Include include = Include.None, string methodologyInfo = null, string contextualInfo = null) { if (verification.ApplyBecause == ApplyBecause.InLieuOfDefaultMessage) { // we force to empty string if null because otherwise when the exception is // constructed the framework chooses some generic message like 'An exception of type ArgumentException was thrown' return(verification.Because ?? string.Empty); } var subjectNameQualifier = assertionTracker.SubjectName == null ? string.Empty : Invariant($" (name: '{assertionTracker.SubjectName}')"); var enumerableQualifier = verifiableItem.ItemIsElementInEnumerable ? " contains an element that" : string.Empty; var methodologyInfoQualifier = methodologyInfo == null ? null : " " + methodologyInfo; var contextualInfoQualifier = contextualInfo == null ? null : " " + contextualInfo; var failingValueQualifier = include.HasFlag(Include.FailingValue) ? (verifiableItem.ItemIsElementInEnumerable ? " Element value" : " Provided value") + Invariant($" is {verifiableItem.ItemValue.ToStringInErrorMessage()}.") : string.Empty; var verificationParametersQualifier = verification.VerificationParameters == null || !verification.VerificationParameters.Any() ? string.Empty : string.Join(string.Empty, verification.VerificationParameters.Select(_ => _.ToStringInErrorMessage())); var result = Invariant($"Provided value{subjectNameQualifier}{enumerableQualifier} {exceptionMessageSuffix}{methodologyInfoQualifier}.{contextualInfoQualifier}{failingValueQualifier}{verificationParametersQualifier}"); if (verification.ApplyBecause == ApplyBecause.PrefixedToDefaultMessage) { if (!string.IsNullOrWhiteSpace(verification.Because)) { result = verification.Because + " " + result; } } else if (verification.ApplyBecause == ApplyBecause.SuffixedToDefaultMessage) { if (!string.IsNullOrWhiteSpace(verification.Because)) { result = result + " " + verification.Because; } } else { throw new NotSupportedException(Invariant($"This {nameof(ApplyBecause)} is not supported: {verification.ApplyBecause}")); } return(result); }
private static AssertionTracker BuildTrackerFromAnonymousObject <TSubject>( [ValidatedNotNull] this TSubject value, string name = null, AssertionKind assertionKind = AssertionKind.Unknown) { var subjectType = typeof(TSubject); AssertionTracker result = null; if (!ReferenceEquals(value, null)) { if (subjectType.IsClosedAnonymousTypeFastCheck()) { // with one property? that's the subject we are trying to apply verification to. var properties = subjectType.GetProperties(); if (properties.Length == 1) { result = new AssertionTracker { SubjectValue = properties[0].GetValue(value, null), SubjectName = name ?? properties[0].Name, SubjectType = properties[0].PropertyType, AssertionKind = assertionKind, }; if (assertionKind != AssertionKind.Unknown) { result.Actions |= Actions.Categorized; } if (result.SubjectName != null) { result.Actions |= Actions.Named; } } else { var errorMessage = string.Format(CultureInfo.InvariantCulture, Verifications.AnonymousObjectDoesNotHaveSinglePropertyErrorMessage, properties.Length, string.Join(", ", properties.Select(_ => _.Name).ToArray())); ThrowImproperUseOfFramework(errorMessage); } } } return(result); }
/// <summary> /// Throws an exception if an improper use of the framework is detected. /// </summary> /// <param name="assertionTracker">The assertion tracker.</param> /// <param name="assertionTrackerShoulds">Specifies what should or should not be true about the assertion tracker.</param> internal static void ThrowImproperUseOfFrameworkIfDetected( [ValidatedNotNull] this AssertionTracker assertionTracker, params AssertionTrackerShould[] assertionTrackerShoulds) { var shouldThrow = false; if (assertionTracker == null) { shouldThrow = true; } else { foreach (var assertionTrackerShould in assertionTrackerShoulds) { switch (assertionTrackerShould) { case AssertionTrackerShould.Exist: shouldThrow = assertionTracker.SubjectType == null; break; case AssertionTrackerShould.NotExist: shouldThrow = true; break; case AssertionTrackerShould.BeCategorized: shouldThrow = (!assertionTracker.Actions.HasFlag(Actions.Categorized)) || (assertionTracker.AssertionKind == AssertionKind.Unknown); break; case AssertionTrackerShould.NotBeCategorized: shouldThrow = assertionTracker.Actions.HasFlag(Actions.Categorized) || (assertionTracker.AssertionKind != AssertionKind.Unknown); break; case AssertionTrackerShould.BeNamed: shouldThrow = (!assertionTracker.Actions.HasFlag(Actions.Named)) || (assertionTracker.SubjectName == null); break; case AssertionTrackerShould.NotBeNamed: shouldThrow = assertionTracker.Actions.HasFlag(Actions.Named) || (assertionTracker.SubjectName != null); break; case AssertionTrackerShould.BeMusted: shouldThrow = !assertionTracker.Actions.HasFlag(Actions.Musted); break; case AssertionTrackerShould.NotBeMusted: shouldThrow = assertionTracker.Actions.HasFlag(Actions.Musted); break; case AssertionTrackerShould.BeEached: shouldThrow = !assertionTracker.Actions.HasFlag(Actions.Eached); break; case AssertionTrackerShould.NotBeEached: shouldThrow = assertionTracker.Actions.HasFlag(Actions.Eached); break; case AssertionTrackerShould.BeVerifiedAtLeastOnce: shouldThrow = !assertionTracker.Actions.HasFlag(Actions.VerifiedAtLeastOnce); break; case AssertionTrackerShould.NotBeVerified: shouldThrow = assertionTracker.Actions.HasFlag(Actions.VerifiedAtLeastOnce); break; default: shouldThrow = true; break; } if (shouldThrow) { break; } } } if (shouldThrow) { ThrowImproperUseOfFramework(Verifications.SubjectAndOperationSequencingErrorMessage); } }
#pragma warning disable SA1201 private static void ExecuteVerification( this AssertionTracker assertionTracker, Verification verification) { assertionTracker.ThrowImproperUseOfFrameworkIfDetected(AssertionTrackerShould.Exist, AssertionTrackerShould.BeMusted); var hasBeenEached = assertionTracker.Actions.HasFlag(Actions.Eached); if (hasBeenEached) { // check that the subject is an IEnumerable and not null if (!assertionTracker.Actions.HasFlag(Actions.VerifiedAtLeastOnce)) { var eachVerification = new Verification { Name = nameof(WorkflowExtensions.Each), }; var eachVerifiableItem = new VerifiableItem { ItemValue = assertionTracker.SubjectValue, ItemType = assertionTracker.SubjectType, ItemIsElementInEnumerable = false, }; ThrowIfNotAssignableToType(eachVerification, eachVerifiableItem, MustBeEnumerableTypeValidations.Single()); NotBeNullInternal(assertionTracker, eachVerification, eachVerifiableItem); } var valueAsEnumerable = (IEnumerable)assertionTracker.SubjectValue; var enumerableElementType = assertionTracker.SubjectType.GetClosedEnumerableElementType(); var verifiableItem = new VerifiableItem { ItemIsElementInEnumerable = true, ItemType = enumerableElementType, }; foreach (var typeValidation in verification.TypeValidations ?? new TypeValidation[] { }) { typeValidation.Handler(verification, verifiableItem, typeValidation); } foreach (var element in valueAsEnumerable) { verifiableItem.ItemValue = element; verification.Handler(assertionTracker, verification, verifiableItem); } } else { var verifiableItem = new VerifiableItem { ItemIsElementInEnumerable = false, ItemValue = assertionTracker.SubjectValue, ItemType = assertionTracker.SubjectType, }; foreach (var typeValidation in verification.TypeValidations ?? new TypeValidation[] { }) { typeValidation.Handler(verification, verifiableItem, typeValidation); } verification.Handler(assertionTracker, verification, verifiableItem); } assertionTracker.Actions |= Actions.VerifiedAtLeastOnce; }