Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Invoking+Awaiting #1051

Merged
merged 1 commit into from May 27, 2019
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
30 changes: 27 additions & 3 deletions Src/FluentAssertions/AssertionExtensions.cs
Expand Up @@ -26,21 +26,45 @@ namespace FluentAssertions
public static partial class AssertionExtensions
{
/// <summary>
/// Invokes the specified action on an subject so that you can chain it with any of the ShouldThrow or ShouldNotThrow
/// overloads.
/// Invokes the specified action on a subject so that you can chain it
/// with any of the assertions from <see cref="ActionAssertions"/>
/// </summary>
[Pure]
public static Action Invoking<T>(this T subject, Action<T> action)
{
return () => action(subject);
}

/// <summary>
/// Invokes the specified action on a subject so that you can chain it
/// with any of the assertions from <see cref="FunctionAssertions{T}"/>
/// </summary>
[Pure]
public static Func<TResult> Invoking<T, TResult>(this T subject, Func<T, TResult> action)
{
return () => action(subject);
}

/// <summary>
/// Invokes the specified action on a subject so that you can chain it
/// with any of the assertions from <see cref="AsyncFunctionAssertions"/>
/// </summary>
[Pure]
public static Func<Task> Awaiting<T>(this T subject, Func<T, Task> action)
{
return () => action(subject);
}

/// <summary>
/// Invokes the specified action on a subject so that you can chain it
/// with any of the assertions from <see cref="AsyncFunctionAssertions"/>
/// </summary>
[Pure]
public static Func<Task<TResult>> Awaiting<T, TResult>(this T subject, Func<T, Task<TResult>> action)
{
return () => action(subject);
}

/// <summary>
/// Provides methods for asserting the execution time of a method or property.
/// </summary>
Expand Down Expand Up @@ -662,7 +686,7 @@ public static FunctionAssertions<T> Should<T>(this Func<T> func)
{
return new FunctionAssertions<T>(func, extractor);
}


#if NET45 || NET47 || NETCOREAPP2_0

Expand Down
48 changes: 48 additions & 0 deletions Tests/Shared.Specs/AsyncFunctionExceptionAssertionSpecs.cs
Expand Up @@ -520,6 +520,49 @@ public void When_async_method_throws_exception_expected_not_to_be_thrown_it_shou
.WithMessage("Did not expect System.ArgumentException, but found one*");
}

[Fact]
public void When_async_method_of_T_succeeds_and_expected_not_to_throw_particular_exception_it_should_succeed()
{
//-----------------------------------------------------------------------------------------------------------
// Arrange
//-----------------------------------------------------------------------------------------------------------
var asyncObject = new AsyncClass();

//-----------------------------------------------------------------------------------------------------------
// Act
//-----------------------------------------------------------------------------------------------------------
Action action = () => asyncObject
.Awaiting(x => asyncObject.ReturnTaskInt())
.Should().NotThrow<InvalidOperationException>();

//-----------------------------------------------------------------------------------------------------------
// Assert
//-----------------------------------------------------------------------------------------------------------
action.Should().NotThrow();
}

[Fact]
public void When_async_method_of_T_throws_exception_expected_not_to_be_thrown_it_should_fail()
{
//-----------------------------------------------------------------------------------------------------------
// Arrange
//-----------------------------------------------------------------------------------------------------------
var asyncObject = new AsyncClass();

//-----------------------------------------------------------------------------------------------------------
// Act
//-----------------------------------------------------------------------------------------------------------
Action action = () => asyncObject
.Awaiting(x => x.ThrowTaskIntAsync<ArgumentException>(true))
.Should().NotThrow<ArgumentException>();

//-----------------------------------------------------------------------------------------------------------
// Assert
//-----------------------------------------------------------------------------------------------------------
action.Should().Throw<XunitException>()
.WithMessage("Did not expect System.ArgumentException, but found one*");
}

[Fact]
public void When_async_method_throws_the_expected_inner_exception_it_should_succeed()
{
Expand Down Expand Up @@ -968,6 +1011,11 @@ public async Task SucceedAsync()
await Task.FromResult(0);
}

public Task<int> ReturnTaskInt()
{
return Task.FromResult(0);
}

public Task IncompleteTask()
{
return new TaskCompletionSource<bool>().Task;
Expand Down
6 changes: 6 additions & 0 deletions Tests/Shared.Specs/ExceptionAssertionSpecs.cs
Expand Up @@ -1132,6 +1132,8 @@ public abstract class Does

public abstract void Do(string someParam);

public abstract int Return();

public static Does Throw<TException>(TException exception)
where TException : Exception
{
Expand Down Expand Up @@ -1159,13 +1161,17 @@ public DoesThrow(TException exception)
public override void Do() => throw exception;

public override void Do(string someParam) => throw exception;

public override int Return() => throw exception;
}

private class DoesNotThrow : Does
{
public override void Do() { }

public override void Do(string someParam) { }

public override int Return() => 42;
}
}

Expand Down
47 changes: 47 additions & 0 deletions Tests/Shared.Specs/ThrowAssertionsSpecs.cs
Expand Up @@ -20,6 +20,20 @@ public void When_subject_throws_expected_exception_it_should_not_do_anything()
testSubject.Invoking(x => x.Do()).Should().Throw<InvalidOperationException>();
}

[Fact]
public void When_func_throws_expected_exception_it_should_not_do_anything()
{
//-----------------------------------------------------------------------------------------------------------
// Arrange
//-----------------------------------------------------------------------------------------------------------
Does testSubject = Does.Throw<InvalidOperationException>();

//-----------------------------------------------------------------------------------------------------------
// Act / Assert
//-----------------------------------------------------------------------------------------------------------
testSubject.Invoking(x => x.Return()).Should().Throw<InvalidOperationException>();
}

[Fact]
public void When_action_throws_expected_exception_it_should_not_do_anything()
{
Expand Down Expand Up @@ -52,6 +66,39 @@ public void When_subject_does_not_throw_exception_but_one_was_expected_it_should
}
}

[Fact]
public void When_func_does_not_throw_exception_but_one_was_expected_it_should_throw_with_clear_description()
{
try
{
Does testSubject = Does.NotThrow();

testSubject.Invoking(x => x.Return()).Should().Throw<Exception>();

throw new XunitException("Should().Throw() did not throw");
}
catch (XunitException ex)
{
ex.Message.Should().Be(
"Expected System.Exception, but no exception was thrown.");
}
}

[Fact]
public void When_func_does_not_throw_it_should_be_chainable()
{
//-----------------------------------------------------------------------------------------------------------
// Arrange
//-----------------------------------------------------------------------------------------------------------
Does testSubject = Does.NotThrow();

//-----------------------------------------------------------------------------------------------------------
// Act / Assert
//-----------------------------------------------------------------------------------------------------------
testSubject.Invoking(x => x.Return()).Should().NotThrow()
.Which.Should().Be(42);
}

[Fact]
public void When_action_does_not_throw_exception_but_one_was_expected_it_should_throw_with_clear_description()
{
Expand Down