/// <summary> /// Use to compose expectations into one matcher /// </summary> /// <param name="continuation">Continuation to operate on</param> /// <param name="expectationsRunner">Runs your composed expectations</param> /// <param name="messageGenerator">Generates the final message, passing in the actual instance being tested as well as a boolean for passed/failed</param> /// <typeparam name="T"></typeparam> public static IMore <T> Compose <T>( this ICanAddMatcher <T> continuation, Action <T> expectationsRunner, Func <T, bool, string> messageGenerator ) { continuation.AddMatcher(actual => { try { expectationsRunner(actual); return(new MatcherResult(true, () => messageGenerator(actual, true))); } catch (UnmetExpectationException e) { return(new MatcherResult(false, () => FinalMessageFor( new[] { "Specifically:", e.Message }, messageGenerator?.Invoke(actual, false) ) )); } }); return(continuation.More()); }
/// <summary> /// Most general matcher add - onto ICanAddMatcher<T> /// </summary> /// <param name="continuation">Continuation to add matcher to</param> /// <param name="matcher">Matcher to run</param> /// <typeparam name="T">Type of the object under test</typeparam> public static IMore <T> AddMatcher <T>( this ICanAddMatcher <T> continuation, Func <T, IMatcherResult> matcher) { AddMatcherPrivate(continuation, matcher); return(continuation.More()); }
/// <summary> /// Use to compose expectations into one matcher /// </summary> /// <param name="continuation">Continuation to operate on</param> /// <param name="expectationsRunner">Runs your composed expectations</param> /// <param name="messageGenerator">Generates the final message, passing in the actual instance being tested as well as a boolean for passed/failed</param> /// <typeparam name="T"></typeparam> public static IMore <T> Compose <T>( this ICanAddMatcher <T> continuation, Action <T> expectationsRunner, Func <T, bool, string> messageGenerator ) { continuation.AddMatcher(actual => { try { // if we're using custom assertions, we won't get an UnmetExpectationException // on a failure // worse, if those custom assertions are from NUnit, we can't stop the failure // -> it's part of the design of NUnit using var _ = Assertions.TemporarilyUseDefaultAssertionsFactoryForThisThread(); expectationsRunner(actual); return(new MatcherResult(true, () => messageGenerator(actual, true))); } catch (UnmetExpectationException e) { return(new MatcherResult(false, () => FinalMessageFor( new[] { "Specifically:", e.Message }, messageGenerator?.Invoke(actual, false) ) )); } }); return(continuation.More()); }
/// <summary> /// Add a matcher onto a Collection continuation /// </summary> /// <param name="continuation">Continuation to add matcher to</param> /// <param name="matcher">Matcher to run</param> /// <typeparam name="T">Type of the object under test</typeparam> public static IMore <IEnumerable <T> > AddMatcher <T>( this ICanAddMatcher <IEnumerable <T> > continuation, Func <IEnumerable <T>, IMatcherResult> matcher ) { AddMatcherPrivate(continuation, matcher); var more = continuation.More(); continuation.CopyPropertiesTo(more); return(more); }
private static IMore <Type> AddInheritsMatcher <TBase>( this ICanAddMatcher <Type> addTo, Func <string> customMessageGenerator ) { addTo.AddMatcher( actual => { var expected = typeof(TBase); if (expected.IsInterface()) { return(new MatcherResult( false, FinalMessageFor( () => new[] { actual.Stringify(), "is not a class." }, customMessageGenerator))); } var passed = expected.IsAssignableFrom(actual); return(new MatcherResult( passed, FinalMessageFor( () => new[] { "Expected", actual.Stringify(), $"{passed.AsNot()}to inherit", expected.Stringify() }, customMessageGenerator ) )); }); return(addTo.More()); }
private static IMore <Type> AddImplementsMatcher( this ICanAddMatcher <Type> addTo, Type shouldImplement, Func <string> customMessage) { addTo.AddMatcher( actual => { var interfaces = actual?.GetAllImplementedInterfaces() ?? new Type[0]; if (!shouldImplement.IsInterface()) { return(new MatcherResult( false, FinalMessageFor( () => new[] { actual.Stringify(), "is not an interface." }, customMessage))); } var passed = interfaces.Contains(shouldImplement); return(new MatcherResult( passed, FinalMessageFor( () => new[] { "Expected", actual.Stringify(), $"{passed.AsNot()}to implement", shouldImplement.Stringify() }, customMessage ) )); }); return(addTo.More()); }