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
2 changes: 1 addition & 1 deletion Pipeline/Build.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ partial class Build : NukeBuild
/// <para />
/// Afterward, you can update the package reference in `Directory.Packages.props` and reset this flag.
/// </summary>
readonly BuildScope BuildScope = BuildScope.Default;
readonly BuildScope BuildScope = BuildScope.CoreOnly;

[Parameter("Github Token")] readonly string GithubToken;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
using System;
using System.Diagnostics.CodeAnalysis;
using System.Text;
using aweXpect.Core.Helpers;

namespace aweXpect.Core.Constraints;

/// <summary>
/// The result of the check if an expectation is met.
/// </summary>
public abstract partial class ConstraintResult
{
/// <summary>
/// A failed <see cref="ConstraintResult" /> due to an <see cref="Exception" />.
/// </summary>
internal class ExceptionConstraintResult : ConstraintResult
{
private readonly Exception _exception;
private readonly ConstraintResult _inner;

/// <summary>
/// A failed <see cref="ConstraintResult" /> due to a thrown <paramref name="exception" />.
/// </summary>
public ExceptionConstraintResult(
ConstraintResult inner,
Exception exception,
ExpectationBuilder expectationBuilder)
: base(inner.Grammars)
{
_inner = inner;
_exception = exception;
FurtherProcessingStrategy = inner.FurtherProcessingStrategy;
expectationBuilder.UpdateContexts(c => c.Add(new ResultContext("Exception", exception.ToString())));
}

public override Outcome Outcome
{
get => Outcome.Failure;
protected set => _inner.Outcome = value;
}

/// <inheritdoc cref="ConstraintResult.AppendExpectation(StringBuilder, string?)" />
public override void AppendExpectation(StringBuilder stringBuilder, string? indentation = null)
=> _inner.AppendExpectation(stringBuilder, indentation);

/// <inheritdoc cref="ConstraintResult.AppendResult(StringBuilder, string?)" />
public override void AppendResult(StringBuilder stringBuilder, string? indentation = null)
{
stringBuilder
.Append("it did throw ");

Type? exceptionType = _exception.GetType();
if (exceptionType == typeof(Exception))
{
stringBuilder.Append("an exception");
}
else
{
stringBuilder.Append(Formatter.Format(exceptionType).PrependAOrAn());
}
}

/// <inheritdoc cref="ConstraintResult.TryGetValue{TValue}(out TValue)" />
public override bool TryGetValue<TValue>([NotNullWhen(true)] out TValue? value)
where TValue : default
=> _inner.TryGetValue(out value);

/// <inheritdoc cref="ConstraintResult.Negate()" />
public override ConstraintResult Negate()
=> _inner.Negate();
}
}
19 changes: 16 additions & 3 deletions Source/aweXpect.Core/Core/ExpectationBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -540,12 +540,25 @@ internal override async Task<ConstraintResult> IsMet(Node rootNode,
timeoutCts.CancelAfter(timeout.Value);
CancellationToken token = timeoutCts.Token;
TValue dataWithTimeout = await _subjectSource.GetValue(timeSystem, token);
Customize.aweXpect.TraceWriter.Value?.WriteMessage($"Checking expectation for {Subject} {dataWithTimeout} with timeout of {Formatter.Format(timeout)}");
Customize.aweXpect.TraceWriter.Value?.WriteMessage(
$"Checking expectation for {Subject} {dataWithTimeout} with timeout of {Formatter.Format(timeout)}");
return await rootNode.IsMetBy(dataWithTimeout, context, token);
}

TValue data = await _subjectSource.GetValue(timeSystem, cancellationToken);
Customize.aweXpect.TraceWriter.Value?.WriteMessage($"Checking expectation for {Subject} {data}");
TValue data;
try
{
data = await _subjectSource.GetValue(timeSystem, cancellationToken);
Customize.aweXpect.TraceWriter.Value?.WriteMessage($"Checking expectation for {Subject} {data}");
}
catch (Exception exception)
{
ConstraintResult expectation = await rootNode.IsMetBy(default(TValue), context, cancellationToken);
Customize.aweXpect.TraceWriter.Value?.WriteMessage(
$"Checking expectation for {Subject} threw an exception");
return new ConstraintResult.ExceptionConstraintResult(expectation, exception, this);
}

return await rootNode.IsMetBy(data, context, cancellationToken);
}
}
20 changes: 20 additions & 0 deletions Tests/aweXpect.Tests/Booleans/ThatBool.IsFalse.Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,26 @@ async Task Act()
await That(Act).DoesNotThrow();
}

[Fact]
public async Task WhenTaskFails_ShouldFailWithExceptionMessage()
{
Task<bool> subject = Task.FromException<bool>(
new NotSupportedException("When Task throws an exception"));

async Task Act()
=> await That(subject).IsFalse().Because("the exception should be logged");

await That(Act).Throws<XunitException>()
.WithMessage("""
Expected that subject
is False, because the exception should be logged,
but it did throw a NotSupportedException

Exception:
System.NotSupportedException: When Task throws an exception
""").AsPrefix();
}

[Fact]
public async Task WhenTrue_ShouldFail()
{
Expand Down
20 changes: 20 additions & 0 deletions Tests/aweXpect.Tests/Booleans/ThatBool.IsTrue.Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,26 @@ but it was False
""");
}

[Fact]
public async Task WhenTaskFails_ShouldFailWithExceptionMessage()
{
Task<bool> subject = Task.FromException<bool>(
new NotSupportedException("When Task throws an exception"));

async Task Act()
=> await That(subject).IsTrue().Because("the exception should be logged");

await That(Act).Throws<XunitException>()
.WithMessage("""
Expected that subject
is True, because the exception should be logged,
but it did throw a NotSupportedException

Exception:
System.NotSupportedException: When Task throws an exception
""").AsPrefix();
}

[Fact]
public async Task WhenTrue_ShouldSucceed()
{
Expand Down
20 changes: 20 additions & 0 deletions Tests/aweXpect.Tests/Booleans/ThatBool.Nullable.IsFalse.Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,26 @@ async Task Act()
await That(Act).DoesNotThrow();
}

[Fact]
public async Task WhenTaskFails_ShouldFailWithExceptionMessage()
{
Task<bool?> subject = Task.FromException<bool?>(
new NotSupportedException("When Task throws an exception"));

async Task Act()
=> await That(subject).IsFalse().Because("the exception should be logged");

await That(Act).Throws<XunitException>()
.WithMessage("""
Expected that subject
is False, because the exception should be logged,
but it did throw a NotSupportedException

Exception:
System.NotSupportedException: When Task throws an exception
""").AsPrefix();
}

[Theory]
[InlineData(true)]
[InlineData(null)]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@ async Task Act()
=> await That(subject).IsNotEqualTo(unexpected);

await That(Act).Throws<XunitException>()
.WithMessage($"""
Expected that subject
is not <null>,
but it was <null>
""");
.WithMessage("""
Expected that subject
is not <null>,
but it was <null>
""");
}

[Theory]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,26 @@ but it was
""");
}

[Fact]
public async Task WhenTaskFails_ShouldFailWithExceptionMessage()
{
Task<bool?> subject = Task.FromException<bool?>(
new NotSupportedException("When Task throws an exception"));

async Task Act()
=> await That(subject).IsNotFalse().Because("the exception should be logged");

await That(Act).Throws<XunitException>()
.WithMessage("""
Expected that subject
is not False, because the exception should be logged,
but it did throw a NotSupportedException

Exception:
System.NotSupportedException: When Task throws an exception
""").AsPrefix();
}

[Theory]
[InlineData(true)]
[InlineData(null)]
Expand Down
20 changes: 20 additions & 0 deletions Tests/aweXpect.Tests/Booleans/ThatBool.Nullable.IsNotTrue.Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,26 @@ async Task Act()
await That(Act).DoesNotThrow();
}

[Fact]
public async Task WhenTaskFails_ShouldFailWithExceptionMessage()
{
Task<bool?> subject = Task.FromException<bool?>(
new NotSupportedException("When Task throws an exception"));

async Task Act()
=> await That(subject).IsNotTrue().Because("the exception should be logged");

await That(Act).Throws<XunitException>()
.WithMessage("""
Expected that subject
is not True, because the exception should be logged,
but it did throw a NotSupportedException

Exception:
System.NotSupportedException: When Task throws an exception
""").AsPrefix();
}

[Fact]
public async Task WhenTrue_ShouldFail()
{
Expand Down
20 changes: 20 additions & 0 deletions Tests/aweXpect.Tests/Booleans/ThatBool.Nullable.IsTrue.Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,26 @@ Expected that subject
""");
}

[Fact]
public async Task WhenTaskFails_ShouldFailWithExceptionMessage()
{
Task<bool?> subject = Task.FromException<bool?>(
new NotSupportedException("When Task throws an exception"));

async Task Act()
=> await That(subject).IsTrue().Because("the exception should be logged");

await That(Act).Throws<XunitException>()
.WithMessage("""
Expected that subject
is True, because the exception should be logged,
but it did throw a NotSupportedException

Exception:
System.NotSupportedException: When Task throws an exception
""").AsPrefix();
}

[Fact]
public async Task WhenTrue_ShouldSucceed()
{
Expand Down