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

Assertions for Func<Task<T>> #990

Closed
jnyrup opened this issue Jan 8, 2019 · 5 comments · Fixed by #1289
Closed

Assertions for Func<Task<T>> #990

jnyrup opened this issue Jan 8, 2019 · 5 comments · Fixed by #1289

Comments

@jnyrup
Copy link
Member

jnyrup commented Jan 8, 2019

Currently both Func<Task> and Func<Task<T>> are handled by AsyncFunctionAssertions which has a Subject of type Func<Task> and hence ignores the return value for Func<Task<T>>.

If we split AsyncFunctionAssertions into:

  • AsyncFunctionAssertions for Func<Task<T>>, and
  • AsyncActionAssertions for Func<Task>

That should enable us to return the result of Task<T> for further assertions, similar to what was implement ed for Func<T> in #951, such as:

// Arrange/Act
Func<Task<int>> func = () => Task.FromResult(42);

// Assert
func.Should().NotThrow().Which.Should().Be(42);
(await func.Should().NotThrowAsync()).Which.Should().Be(42);

This was inspired by this question

@dennisdoomen
Copy link
Member

Yeah, sounds like a good idea.

@lg2de
Copy link
Contributor

lg2de commented Feb 27, 2019

I would like to combine this extension with an additional feature:

func.Should().Complete(TimeSpan.FromMilliseconds(100));

The test would fail if the Task does not complete within specified time span.

What do you think about such feature?

@dennisdoomen
Copy link
Member

That's a nice idea, and a very useful one as well.

@lg2de
Copy link
Contributor

lg2de commented Feb 28, 2019

While thinking about the implementation I would like to check whether my "Complete" extension should be based on Func<Task<T>> or maybe better on Task<T>.
The latter would result into easier usage:

this.myServer.OpenAsync().Should().Complete(TimeSpan.FromMilliseconds(100));

In this case my changes would not touch anymore the refactoring mentioned by @jnyrup.
Should I create another issue therefore before providing a pull request?

@jnyrup
Copy link
Member Author

jnyrup commented Feb 28, 2019

@lg2de I would prefer if you opened a new issue with an API proposal describing the purpose of the functions and their function signatures.

@jnyrup jnyrup added this to the 6.0 milestone Nov 18, 2019
jnyrup added a commit to jnyrup/fluentassertions that referenced this issue Mar 30, 2020
This PR enables you to continue asserting on the result of `Func<Task<int>>` when it does not throw.

```c#
Func<Task<int>> func = () => Task.FromResult(42);

func.Should().NotThrow()
    .Which.Should().Be(42);

(await func.Should().NotThrowAsync())
    .Which.Should().Be(42);

func.Should().NotThrowAfter(10.Seconds(), 1.Seconds())
    .Which.Should().Be(42)

(await func.Should().NotThrowAfterAsync(10.Seconds(), 1.Seconds()))
    .Which.Should().Be(42);
```

The implementations and tests are mostly copied from the non-generic or sync versions.
To avoid the redefinitions of `Subject` in each class two changes in generics:
* `DelegateAssertions` and `AsyncFunctionAssertions` are now generic in `TAssertions`.
* `AsyncFunctionAssertions` is also generic in `TTask : Task` to support
  both `Task` and `Task<T>` equally.

This fixes fluentassertions#990
jnyrup added a commit to jnyrup/fluentassertions that referenced this issue Apr 10, 2020
This PR enables you to continue asserting on the result of `Func<Task<int>>` when it does not throw.

```c#
Func<Task<int>> func = () => Task.FromResult(42);

func.Should().NotThrow()
    .Which.Should().Be(42);

(await func.Should().NotThrowAsync())
    .Which.Should().Be(42);

func.Should().NotThrowAfter(10.Seconds(), 1.Seconds())
    .Which.Should().Be(42)

(await func.Should().NotThrowAfterAsync(10.Seconds(), 1.Seconds()))
    .Which.Should().Be(42);
```

The implementations and tests are mostly copied from the non-generic or sync versions.
To avoid the redefinitions of `Subject` in each class two changes in generics:
* `DelegateAssertions` and `AsyncFunctionAssertions` are now generic in `TAssertions`.
* `AsyncFunctionAssertions` is also generic in `TTask : Task` to support
  both `Task` and `Task<T>` equally.

This fixes fluentassertions#990
jnyrup added a commit to jnyrup/fluentassertions that referenced this issue Apr 10, 2020
This PR enables you to continue asserting on the result of `Func<Task<int>>` when it does not throw.

```c#
Func<Task<int>> func = () => Task.FromResult(42);

func.Should().NotThrow()
    .Which.Should().Be(42);

(await func.Should().NotThrowAsync())
    .Which.Should().Be(42);

func.Should().NotThrowAfter(10.Seconds(), 1.Seconds())
    .Which.Should().Be(42)

(await func.Should().NotThrowAfterAsync(10.Seconds(), 1.Seconds()))
    .Which.Should().Be(42);
```

The implementations and tests are mostly copied from the non-generic or sync versions.
To avoid the redefinitions of `Subject` in each class two changes in generics:
* `DelegateAssertions` and `AsyncFunctionAssertions` are now generic in `TAssertions`.
* `AsyncFunctionAssertions` is also generic in `TTask : Task` to support
  both `Task` and `Task<T>` equally.

This fixes fluentassertions#990
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants