Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Expand Up @@ -16,15 +16,15 @@ public sealed partial class WithValue<T>
/// <summary>
/// Verifies that the delegate does not throw any exception.
/// </summary>
public AndResult<T, WithValue<T>> DoesNotThrow()
public DelegateWithValueResult<T> DoesNotThrow()
=> new(ExpectationBuilder.AddConstraint((it, grammars) =>
new DoesNotThrowConstraint(it, grammars, typeof(Exception))),
this);

/// <summary>
/// Verifies that the delegate does not throw an exception of type <typeparamref name="TException" />.
/// </summary>
public AndResult<T, WithValue<T>> DoesNotThrow<TException>()
public DelegateWithValueResult<T> DoesNotThrow<TException>()
where TException : Exception
=> new(ExpectationBuilder.AddConstraint((it, grammars) =>
new DoesNotThrowConstraint(it, grammars, typeof(TException))),
Expand All @@ -33,7 +33,7 @@ public AndResult<T, WithValue<T>> DoesNotThrow<TException>()
/// <summary>
/// Verifies that the delegate does not throw an exception of type <paramref name="exceptionType" />.
/// </summary>
public AndResult<T, WithValue<T>> DoesNotThrow(Type exceptionType)
public DelegateWithValueResult<T> DoesNotThrow(Type exceptionType)
=> new(ExpectationBuilder.AddConstraint((it, grammars) =>
new DoesNotThrowConstraint(it, grammars, exceptionType)),
this);
Expand Down
84 changes: 84 additions & 0 deletions Source/aweXpect.Core/Results/DelegateWithValueResult.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
using System.Diagnostics.CodeAnalysis;
using System.Text;
using aweXpect.Core;
using aweXpect.Core.Constraints;
using aweXpect.Core.Sources;
using aweXpect.Delegates;

namespace aweXpect.Results;

/// <summary>
/// Result for a delegate with a value that does not throw.
/// </summary>
public class DelegateWithValueResult<T>(ExpectationBuilder expectationBuilder, ThatDelegate.WithValue<T> returnValue)
: AndResult<T, ThatDelegate.WithValue<T>>(expectationBuilder, returnValue)
Comment thread
vbreuss marked this conversation as resolved.
{
private readonly ExpectationBuilder _expectationBuilder = expectationBuilder;

/// <summary>
/// Returns the result returned from the delegate.
/// </summary>
public IThat<T> AndWhoseResult
{
get
{
_expectationBuilder.And("")
.AddConstraint((it, grammars) => new DoesNotThrowAnyExceptionConstraint(it, grammars))
.ForWhich<DelegateValue<T>, T?>(d => d.Value, " and whose result ", "the result");
return new ThatSubject<T?>(_expectationBuilder);
}
}

private sealed class DoesNotThrowAnyExceptionConstraint(
string it,
ExpectationGrammars grammars)
: ConstraintResult(grammars),
IValueConstraint<DelegateValue<T>>
{
private DelegateValue<T>? _actual;

/// <inheritdoc />
public ConstraintResult IsMetBy(DelegateValue<T> value)
{
_actual = value;
if (value.IsNull)
{
Outcome = Outcome.Failure;
return this;
}

Outcome = value.Exception is null
? Outcome.Success
: Outcome.Failure;
return this;
}

public override void AppendExpectation(StringBuilder stringBuilder, string? indentation = null)
{
// Do not append any expectation
}

public override void AppendResult(StringBuilder stringBuilder, string? indentation = null)
{
if (_actual?.Exception is not null)
{
stringBuilder.Append(it).Append(" did throw ");
stringBuilder.Append(ThatDelegate.FormatForMessage(_actual.Exception));
}
}

public override bool TryGetValue<TValue>([NotNullWhen(true)] out TValue? value) where TValue : default
{
if (_actual is { Value: TValue typedValue, })
{
value = typedValue;
return true;
}

value = default;
return typeof(TValue).IsAssignableFrom(typeof(T));
}

public override ConstraintResult Negate() => this;
}
}
11 changes: 8 additions & 3 deletions Tests/aweXpect.Core.Api.Tests/Expected/aweXpect.Core_net8.0.txt
Original file line number Diff line number Diff line change
Expand Up @@ -463,9 +463,9 @@ namespace aweXpect.Delegates
public sealed class WithValue<T> : aweXpect.Delegates.ThatDelegate, aweXpect.Core.IExpectThat<aweXpect.Delegates.ThatDelegate.WithValue<T>>, aweXpect.Core.IThat<aweXpect.Delegates.ThatDelegate.WithValue<T>>
{
public WithValue(aweXpect.Core.ExpectationBuilder expectationBuilder) { }
public aweXpect.Results.AndResult<T, aweXpect.Delegates.ThatDelegate.WithValue<T>> DoesNotThrow() { }
public aweXpect.Results.AndResult<T, aweXpect.Delegates.ThatDelegate.WithValue<T>> DoesNotThrow(System.Type exceptionType) { }
public aweXpect.Results.AndResult<T, aweXpect.Delegates.ThatDelegate.WithValue<T>> DoesNotThrow<TException>()
public aweXpect.Results.DelegateWithValueResult<T> DoesNotThrow() { }
public aweXpect.Results.DelegateWithValueResult<T> DoesNotThrow(System.Type exceptionType) { }
public aweXpect.Results.DelegateWithValueResult<T> DoesNotThrow<TException>()
where TException : System.Exception { }
public aweXpect.Results.AndResult<T, aweXpect.Delegates.ThatDelegate.WithValue<T>> DoesNotThrowExactly(System.Type exceptionType) { }
public aweXpect.Results.AndResult<T, aweXpect.Delegates.ThatDelegate.WithValue<T>> DoesNotThrowExactly<TException>()
Expand Down Expand Up @@ -999,6 +999,11 @@ namespace aweXpect.Results
public TTarget Once() { }
public TTarget Twice() { }
}
public class DelegateWithValueResult<T> : aweXpect.Results.AndResult<T, aweXpect.Delegates.ThatDelegate.WithValue<T>>
{
public DelegateWithValueResult(aweXpect.Core.ExpectationBuilder expectationBuilder, aweXpect.Delegates.ThatDelegate.WithValue<T> returnValue) { }
public aweXpect.Core.IThat<T> AndWhoseResult { get; }
}
public class ExecutesInResult<TResult>
{
public ExecutesInResult(TResult returnValue, aweXpect.Options.TimeSpanEqualityOptions options) { }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -463,9 +463,9 @@ namespace aweXpect.Delegates
public sealed class WithValue<T> : aweXpect.Delegates.ThatDelegate, aweXpect.Core.IExpectThat<aweXpect.Delegates.ThatDelegate.WithValue<T>>, aweXpect.Core.IThat<aweXpect.Delegates.ThatDelegate.WithValue<T>>
{
public WithValue(aweXpect.Core.ExpectationBuilder expectationBuilder) { }
public aweXpect.Results.AndResult<T, aweXpect.Delegates.ThatDelegate.WithValue<T>> DoesNotThrow() { }
public aweXpect.Results.AndResult<T, aweXpect.Delegates.ThatDelegate.WithValue<T>> DoesNotThrow(System.Type exceptionType) { }
public aweXpect.Results.AndResult<T, aweXpect.Delegates.ThatDelegate.WithValue<T>> DoesNotThrow<TException>()
public aweXpect.Results.DelegateWithValueResult<T> DoesNotThrow() { }
public aweXpect.Results.DelegateWithValueResult<T> DoesNotThrow(System.Type exceptionType) { }
public aweXpect.Results.DelegateWithValueResult<T> DoesNotThrow<TException>()
where TException : System.Exception { }
public aweXpect.Results.AndResult<T, aweXpect.Delegates.ThatDelegate.WithValue<T>> DoesNotThrowExactly(System.Type exceptionType) { }
public aweXpect.Results.AndResult<T, aweXpect.Delegates.ThatDelegate.WithValue<T>> DoesNotThrowExactly<TException>()
Expand Down Expand Up @@ -982,6 +982,11 @@ namespace aweXpect.Results
public TTarget Once() { }
public TTarget Twice() { }
}
public class DelegateWithValueResult<T> : aweXpect.Results.AndResult<T, aweXpect.Delegates.ThatDelegate.WithValue<T>>
{
public DelegateWithValueResult(aweXpect.Core.ExpectationBuilder expectationBuilder, aweXpect.Delegates.ThatDelegate.WithValue<T> returnValue) { }
public aweXpect.Core.IThat<T> AndWhoseResult { get; }
}
public class ExecutesInResult<TResult>
{
public ExecutesInResult(TResult returnValue, aweXpect.Options.TimeSpanEqualityOptions options) { }
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
namespace aweXpect.Tests;

public sealed partial class ThatDelegate
{
public sealed partial class DoesNotThrow
{
public sealed class AndWhoseResult
{
public sealed class Tests
{
[Fact]
public async Task WhenDelegateThrows_ShouldFail()
{
Func<int> @delegate = () => throw new CustomException();

async Task Act() => await That(@delegate).DoesNotThrow().AndWhoseResult.IsGreaterThan(5);

await That(Act).Throws<XunitException>()
.WithMessage("""
Expected that @delegate
does not throw any exception and whose result is greater than 5,
but it did throw a ThatDelegate.CustomException:
WhenDelegateThrows_ShouldFail
""");
}

[Theory]
[AutoData]
public async Task WhenReturnValueDoesNotMatch_ShouldFail(int value)
{
Func<int> @delegate = () => value;

async Task Act() => await That(@delegate).DoesNotThrow().AndWhoseResult.IsLessThan(value);

await That(Act).Throws<XunitException>()
.WithMessage($"""
Expected that @delegate
does not throw any exception and whose result is less than {value},
but the result was {value}
""");
}

[Theory]
[AutoData]
public async Task WhenReturnValueMatches_ShouldSucceed(int value)
{
Func<int> @delegate = () => value;

await That(@delegate).DoesNotThrow().AndWhoseResult.IsEqualTo(value);
}
}

public sealed class GenericTests
{
[Fact]
public async Task WhenDelegateThrowsExpectedException_ShouldFail()
{
Func<int> @delegate = () => throw new CustomException();

async Task Act()
=> await That(@delegate).DoesNotThrow<CustomException>().AndWhoseResult.IsEqualTo(5);

await That(Act).Throws<XunitException>()
.WithMessage("""
Expected that @delegate
does not throw a ThatDelegate.CustomException and whose result is equal to 5,
but it did throw a ThatDelegate.CustomException:
WhenDelegateThrowsExpectedException_ShouldFail
""");
}

[Fact]
public async Task WhenDelegateThrowsOtherException_ShouldFail()
{
Func<int> @delegate = () => throw new CustomException();

async Task Act()
=> await That(@delegate).DoesNotThrow<OtherException>().AndWhoseResult.IsEqualTo(5);

await That(Act).Throws<XunitException>()
.WithMessage("""
Expected that @delegate
does not throw a ThatDelegate.OtherException and whose result is equal to 5,
but it did throw a ThatDelegate.CustomException:
WhenDelegateThrowsOtherException_ShouldFail
""");
}

[Theory]
[AutoData]
public async Task WhenReturnValueDoesNotMatch_ShouldFail(int value)
{
Func<int> @delegate = () => value;

async Task Act() => await That(@delegate).DoesNotThrow<CustomException>().AndWhoseResult
.IsEqualTo(value + 1);

await That(Act).Throws<XunitException>()
.WithMessage($"""
Expected that @delegate
does not throw a ThatDelegate.CustomException and whose result is equal to {value + 1},
but the result was {value} which differs by -1
""");
}

[Theory]
[AutoData]
public async Task WhenReturnValueMatches_ShouldSucceed(int value)
{
Func<int> @delegate = () => value;

await That(@delegate).DoesNotThrow<CustomException>().AndWhoseResult.IsEqualTo(value);
}
}

public sealed class TypeTests
{
[Fact]
public async Task WhenDelegateThrowsExpectedException_ShouldFail()
{
Func<int> @delegate = () => throw new CustomException();

async Task Act()
=> await That(@delegate).DoesNotThrow(typeof(CustomException)).AndWhoseResult.IsEqualTo(5);

await That(Act).Throws<XunitException>()
.WithMessage("""
Expected that @delegate
does not throw a ThatDelegate.CustomException and whose result is equal to 5,
but it did throw a ThatDelegate.CustomException:
WhenDelegateThrowsExpectedException_ShouldFail
""");
}

[Fact]
public async Task WhenDelegateThrowsOtherException_ShouldFail()
{
Func<int> @delegate = () => throw new CustomException();

async Task Act()
=> await That(@delegate).DoesNotThrow(typeof(OtherException)).AndWhoseResult.IsEqualTo(5);

await That(Act).Throws<XunitException>()
.WithMessage("""
Expected that @delegate
does not throw a ThatDelegate.OtherException and whose result is equal to 5,
but it did throw a ThatDelegate.CustomException:
WhenDelegateThrowsOtherException_ShouldFail
""");
}

[Theory]
[AutoData]
public async Task WhenReturnValueDoesNotMatch_ShouldFail(int value)
{
Func<int> @delegate = () => value;

async Task Act() => await That(@delegate).DoesNotThrow(typeof(CustomException)).AndWhoseResult
.IsEqualTo(value + 1);

await That(Act).Throws<XunitException>()
.WithMessage($"""
Expected that @delegate
does not throw a ThatDelegate.CustomException and whose result is equal to {value + 1},
but the result was {value} which differs by -1
""");
}

[Theory]
[AutoData]
public async Task WhenReturnValueMatches_ShouldSucceed(int value)
{
Func<int> @delegate = () => value;

await That(@delegate).DoesNotThrow(typeof(CustomException)).AndWhoseResult.IsEqualTo(value);
}
}
}
}
}