Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions Docs/pages/docs/expectations/06-delegates.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,12 @@ This is especially useful with parametrized tests where it depends on a paramete
You can verify the message of the thrown exception:

```csharp
void Act() => throw new CustomException("my exception");
void Act() => throw new CustomException("This is my exception text");

await Expect.That(Act).ThrowsException().WithMessage("my exception");
await Expect.That(Act).ThrowsException().WithMessage("This is my exception text");
await Expect.That(Act).ThrowsException().WithoutMessage("some other text");
await Expect.That(Act).ThrowsException().WithMessageContaining("my exception");
await Expect.That(Act).ThrowsException().WithoutMessageContaining("something else");
```

You can use the same configuration options as when [comparing strings](/docs/expectations/string#equality).
Expand Down
22 changes: 22 additions & 0 deletions Source/aweXpect/That/Delegates/ThatDelegateThrows.WithMessage.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using aweXpect.Core;
using aweXpect.Core.Constraints;
using aweXpect.Delegates;
using aweXpect.Options;
using aweXpect.Results;
Expand Down Expand Up @@ -28,4 +29,25 @@ public static StringEqualityTypeResult<TException, ThatDelegateThrows<TException
source,
options);
}

/// <summary>
/// Verifies that the thrown exception does not have a message equal to <paramref name="unexpected" />.
/// </summary>
public static StringEqualityTypeResult<TException, ThatDelegateThrows<TException>> WithoutMessage<TException>(
this ThatDelegateThrows<TException> source,
string unexpected)
where TException : Exception?
{
StringEqualityOptions options = new();
return new StringEqualityTypeResult<TException, ThatDelegateThrows<TException>>(
source.ExpectationBuilder.AddConstraint((it, grammars)
=> new ThatException.HasMessageValueConstraint(
source.ExpectationBuilder,
it,
grammars | ExpectationGrammars.Active | ExpectationGrammars.Nested,
unexpected,
options).Invert()),
source,
options);
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using aweXpect.Core;
using aweXpect.Core.Constraints;
using aweXpect.Delegates;
using aweXpect.Options;
using aweXpect.Results;
Expand Down Expand Up @@ -28,4 +29,26 @@ public static StringEqualityResult<TException, ThatDelegateThrows<TException>> W
source,
options);
}

/// <summary>
/// Verifies that the thrown exception does not have a message that contains the <paramref name="unexpected" />
/// pattern.
/// </summary>
public static StringEqualityResult<TException, ThatDelegateThrows<TException>> WithoutMessageContaining<TException>(
this ThatDelegateThrows<TException> source,
string? unexpected)
where TException : Exception?
{
StringEqualityOptions options = new();
return new StringEqualityResult<TException, ThatDelegateThrows<TException>>(
source.ExpectationBuilder.AddConstraint((it, grammars)
=> new ThatException.HasMessageContainingConstraint(
source.ExpectationBuilder,
it,
grammars | ExpectationGrammars.Active | ExpectationGrammars.Nested,
unexpected,
options).Invert()),
source,
options);
}
}
24 changes: 20 additions & 4 deletions Source/aweXpect/That/Exceptions/ThatException.HasMessage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,23 +27,39 @@ public static partial class ThatException
options);
}

/// <summary>
/// Verifies that the actual exception does not have a message equal to <paramref name="unexpected" />.
/// </summary>
public static StringEqualityTypeResult<Exception?, IThat<Exception?>> DoesNotHaveMessage(
this IThat<Exception?> source,
string unexpected)
{
StringEqualityOptions options = new();
return new StringEqualityTypeResult<Exception?, IThat<Exception?>>(
source.Get().ExpectationBuilder.AddConstraint((expectationBuilder, it, grammars)
=> new HasMessageValueConstraint(
expectationBuilder, it, grammars, unexpected, options).Invert()),
source,
options);
}

internal class HasMessageValueConstraint(
ExpectationBuilder expectationBuilder,
string it,
ExpectationGrammars grammars,
string expected,
StringEqualityOptions options)
: ConstraintResult.WithValue<Exception?>(grammars),
: ConstraintResult.WithNotNullValue<Exception?>(it, grammars),
IAsyncConstraint<Exception?>
{
public async Task<ConstraintResult> IsMetBy(Exception? actual, CancellationToken cancellationToken)
{
Actual = actual;
Outcome = await options.AreConsideredEqual(actual?.Message, expected) ? Outcome.Success : Outcome.Failure;
if (Outcome == Outcome.Failure)
if (!string.IsNullOrEmpty(actual?.Message))
Comment thread
vbreuss marked this conversation as resolved.
{
expectationBuilder.UpdateContexts(contexts => contexts
.Add(new ResultContext("Message", actual?.Message)));
.Add(new ResultContext("Message", actual.Message)));
}
Comment thread
vbreuss marked this conversation as resolved.

return this;
Expand All @@ -70,7 +86,7 @@ protected override void AppendNormalExpectation(StringBuilder stringBuilder, str
}

protected override void AppendNormalResult(StringBuilder stringBuilder, string? indentation = null)
=> stringBuilder.Append(options.GetExtendedFailure(it, Grammars, Actual?.Message, expected));
=> stringBuilder.Append(options.GetExtendedFailure(It, Grammars, Actual?.Message, expected));

protected override void AppendNegatedExpectation(StringBuilder stringBuilder, string? indentation = null)
=> AppendNormalExpectation(stringBuilder, indentation);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,29 @@ public static partial class ThatException
options);
}

/// <summary>
/// Verifies that the actual exception does not have a message containing the <paramref name="unexpected" /> pattern.
/// </summary>
public static StringEqualityTypeResult<Exception?, IThat<Exception?>> DoesNotHaveMessageContaining(
this IThat<Exception?> source,
string? unexpected)
{
StringEqualityOptions options = new();
return new StringEqualityTypeResult<Exception?, IThat<Exception?>>(
source.Get().ExpectationBuilder.AddConstraint((expectationBuilder, it, grammars)
=> new HasMessageContainingConstraint(
expectationBuilder, it, grammars, unexpected, options).Invert()),
source,
options);
}

internal class HasMessageContainingConstraint(
ExpectationBuilder expectationBuilder,
string it,
ExpectationGrammars grammars,
string? expected,
StringEqualityOptions options)
: ConstraintResult.WithValue<Exception?>(grammars),
: ConstraintResult.WithNotNullValue<Exception?>(it, grammars),
Comment thread
vbreuss marked this conversation as resolved.
IAsyncConstraint<Exception?>
{
public async Task<ConstraintResult> IsMetBy(Exception? actual, CancellationToken cancellationToken)
Expand All @@ -43,10 +59,10 @@ public async Task<ConstraintResult> IsMetBy(Exception? actual, CancellationToken
Outcome = expected is null || await options.AreConsideredEqual(actual?.Message, $"*{expected}*")
? Outcome.Success
: Outcome.Failure;
if (Outcome == Outcome.Failure)
if (!string.IsNullOrEmpty(actual?.Message))
{
expectationBuilder.UpdateContexts(contexts => contexts
.Add(new ResultContext("Message", actual?.Message)));
.Add(new ResultContext("Message", actual.Message)));
Comment thread
vbreuss marked this conversation as resolved.
}

return this;
Expand All @@ -57,42 +73,46 @@ protected override void AppendNormalExpectation(StringBuilder stringBuilder, str
ExpectationGrammars equalityGrammars = Grammars;
if (Grammars.HasFlag(ExpectationGrammars.Active))
{
stringBuilder.Append("with Message containing ");
stringBuilder.Append("with Message containing matching ");
equalityGrammars &= ~ExpectationGrammars.Active;
}
else if (Grammars.HasFlag(ExpectationGrammars.Nested))
{
stringBuilder.Append("Message contains ");
stringBuilder.Append("Message contains matching ");
}
else
{
stringBuilder.Append("contains Message ");
stringBuilder.Append("contains Message matching ");
}

stringBuilder.Append(options.GetExpectation(expected, equalityGrammars));
options.Exactly();
stringBuilder.Append(options.GetExpectation(expected, equalityGrammars)["equal to ".Length..]);
options.AsWildcard();
}

protected override void AppendNormalResult(StringBuilder stringBuilder, string? indentation = null)
=> stringBuilder.Append(options.GetExtendedFailure(it, Grammars, Actual?.Message, expected));
=> stringBuilder.Append(options.GetExtendedFailure(It, Grammars, Actual?.Message, expected));

protected override void AppendNegatedExpectation(StringBuilder stringBuilder, string? indentation = null)
{
ExpectationGrammars equalityGrammars = Grammars;
if (Grammars.HasFlag(ExpectationGrammars.Active))
{
stringBuilder.Append("with Message not containing ");
stringBuilder.Append("with Message not containing matching ");
equalityGrammars &= ~ExpectationGrammars.Active;
}
else if (Grammars.HasFlag(ExpectationGrammars.Nested))
{
stringBuilder.Append("Message does not contain ");
stringBuilder.Append("Message does not contain matching ");
}
else
{
stringBuilder.Append("does not contain Message ");
stringBuilder.Append("does not contain Message matching ");
}

stringBuilder.Append(options.GetExpectation(expected, equalityGrammars.Negate()));
options.Exactly();
stringBuilder.Append(options.GetExpectation(expected, equalityGrammars.Negate())["equal to ".Length..]);
options.AsWildcard();
}

protected override void AppendNegatedResult(StringBuilder stringBuilder, string? indentation = null)
Expand Down
6 changes: 6 additions & 0 deletions Tests/aweXpect.Api.Tests/Expected/aweXpect_net8.0.txt
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,10 @@ namespace aweXpect
where TException : System.ArgumentException? { }
public static aweXpect.Results.AndOrResult<TException?, aweXpect.Delegates.ThatDelegateThrows<TException>> WithRecursiveInnerExceptions<TException>(this aweXpect.Delegates.ThatDelegateThrows<TException> source, System.Action<aweXpect.Core.IThat<System.Collections.Generic.IEnumerable<System.Exception>>> expectations)
where TException : System.Exception? { }
public static aweXpect.Results.StringEqualityTypeResult<TException, aweXpect.Delegates.ThatDelegateThrows<TException>> WithoutMessage<TException>(this aweXpect.Delegates.ThatDelegateThrows<TException> source, string unexpected)
where TException : System.Exception? { }
public static aweXpect.Results.StringEqualityResult<TException, aweXpect.Delegates.ThatDelegateThrows<TException>> WithoutMessageContaining<TException>(this aweXpect.Delegates.ThatDelegateThrows<TException> source, string? unexpected)
where TException : System.Exception? { }
}
public static class ThatDictionary
{
Expand Down Expand Up @@ -706,6 +710,8 @@ namespace aweXpect
}
public static class ThatException
{
public static aweXpect.Results.StringEqualityTypeResult<System.Exception?, aweXpect.Core.IThat<System.Exception?>> DoesNotHaveMessage(this aweXpect.Core.IThat<System.Exception?> source, string unexpected) { }
public static aweXpect.Results.StringEqualityTypeResult<System.Exception?, aweXpect.Core.IThat<System.Exception?>> DoesNotHaveMessageContaining(this aweXpect.Core.IThat<System.Exception?> source, string? unexpected) { }
public static aweXpect.Results.AndOrResult<TException, aweXpect.Core.IThat<TException>> HasHResult<TException>(this aweXpect.Core.IThat<TException> source, int expected)
where TException : System.Exception? { }
public static aweXpect.Results.AndOrResult<System.Exception?, aweXpect.Core.IThat<System.Exception?>> HasInner(this aweXpect.Core.IThat<System.Exception?> source, System.Type innerExceptionType) { }
Expand Down
6 changes: 6 additions & 0 deletions Tests/aweXpect.Api.Tests/Expected/aweXpect_netstandard2.0.txt
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,10 @@ namespace aweXpect
where TException : System.ArgumentException? { }
public static aweXpect.Results.AndOrResult<TException?, aweXpect.Delegates.ThatDelegateThrows<TException>> WithRecursiveInnerExceptions<TException>(this aweXpect.Delegates.ThatDelegateThrows<TException> source, System.Action<aweXpect.Core.IThat<System.Collections.Generic.IEnumerable<System.Exception>>> expectations)
where TException : System.Exception? { }
public static aweXpect.Results.StringEqualityTypeResult<TException, aweXpect.Delegates.ThatDelegateThrows<TException>> WithoutMessage<TException>(this aweXpect.Delegates.ThatDelegateThrows<TException> source, string unexpected)
where TException : System.Exception? { }
public static aweXpect.Results.StringEqualityResult<TException, aweXpect.Delegates.ThatDelegateThrows<TException>> WithoutMessageContaining<TException>(this aweXpect.Delegates.ThatDelegateThrows<TException> source, string? unexpected)
where TException : System.Exception? { }
}
public static class ThatDictionary
{
Expand Down Expand Up @@ -469,6 +473,8 @@ namespace aweXpect
}
public static class ThatException
{
public static aweXpect.Results.StringEqualityTypeResult<System.Exception?, aweXpect.Core.IThat<System.Exception?>> DoesNotHaveMessage(this aweXpect.Core.IThat<System.Exception?> source, string unexpected) { }
public static aweXpect.Results.StringEqualityTypeResult<System.Exception?, aweXpect.Core.IThat<System.Exception?>> DoesNotHaveMessageContaining(this aweXpect.Core.IThat<System.Exception?> source, string? unexpected) { }
public static aweXpect.Results.AndOrResult<TException, aweXpect.Core.IThat<TException>> HasHResult<TException>(this aweXpect.Core.IThat<TException> source, int expected)
where TException : System.Exception? { }
public static aweXpect.Results.AndOrResult<System.Exception?, aweXpect.Core.IThat<System.Exception?>> HasInner(this aweXpect.Core.IThat<System.Exception?> source, System.Type innerExceptionType) { }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,9 @@ Expected that action
throws an exception with an inner MyException whose Message is equal to "foo",
but it was a ThatDelegate.CustomException:
foo

Message:
foo
""");
}

Expand Down Expand Up @@ -480,6 +483,9 @@ Expected that action
throws an exception with an inner MyException whose Message is equal to "foo",
but it was a ThatDelegate.CustomException:
foo

Message:
foo
""");
}

Expand Down
Loading
Loading