-
-
Notifications
You must be signed in to change notification settings - Fork 804
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
Add ability to set up the .Result
of (value) tasks
#1126
Conversation
Split(memberAccessExpression.Expression, out r, out p); | ||
p.AddResultExpression( | ||
awaitable => Expression.MakeMemberAccess(awaitable, memberAccessExpression.Member), | ||
awaitableFactory); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Once we add support for custom awaitable types, it will be better to preserve the original expression, instead of replacing the .Result
access with a new result expression.
if (this.result is ExceptionResult r) | ||
{ | ||
this.result = awaitableFactory.CreateFaulted(r.Exception); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There may be circumstances where we may have to call the other CreateFaulted(IEnumerable<Exception> exceptions)
overload instead (which, I'm assuming, is meant to cover AggregateException
). I haven't yet looked into whether this is actually necessary. Perhaps it would be better to remove that other overload until that time?
catch (Exception exception) | ||
{ | ||
invocation.Exception = exception; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We may have to change this some day in order to account for several / aggregate exceptions.
97a506f
to
6f6a89d
Compare
Bumps [Moq](https://github.com/moq/moq4) from 4.15.2 to 4.16.0. #Changelog *Sourced from [Moq's changelog](https://github.com/moq/moq4/blob/main/CHANGELOG.md).* > ## 4.16.0 (2021-01-16) > > #### Added > > * Ability to directly set up the `.Result` of tasks and value tasks, which makes setup expressions more uniform by rendering dedicated async verbs like `.ReturnsAsync`, `.ThrowsAsync`, etc. unnecessary: > > ```diff > -mock.Setup(x => x.GetFooAsync()).ReturnsAsync(foo) > +mock.Setup(x => x.GetFooAsync().Result).Returns(foo) > ``` > > This is useful in places where there currently aren't any such async verbs at all: > > ```diff > -Mock.Of<X>(x => x.GetFooAsync() == Task.FromResult(foo)) > +Mock.Of<X>(x => x.GetFooAsync().Result == foo) > ``` > > This also allows recursive setups / method chaining across async calls inside a single setup expression: > > ```diff > -mock.Setup(x => x.GetFooAsync()).ReturnsAsync(Mock.Of<IFoo>(f => f.Bar == bar)) > +mock.Setup(x => x.GetFooAsync().Result.Bar).Returns(bar) > ``` > > or, with only `Mock.Of`: > > ```diff > -Mock.Of<X>(x => x.GetFooAsync() == Task.FromResult(Mock.Of<IFoo>(f => f.Bar == bar))) > +Mock.Of<X>(x => x.GetFooAsync().Result.Bar == bar) > ``` > > This should work in all principal setup methods (`Mock.Of`, `mock.Setup…`, `mock.Verify…`). Support in `mock.Protected()` and for custom awaitable types may be added in the future. (@stakx, [#1126](devlooped/moq#1126)) > > #### Changed > > * Attempts to mark conditionals setup as verifiable are once again allowed; it turns out that forbidding it (as was done in [#997](devlooped/moq#997) for version 4.14.0) is in fact a regression. (@stakx, [#1121](devlooped/moq#1121)) > > #### Fixed > > * Performance regression: Adding setups to a mock becomes slower with each setup (@CeesKaas, [#1110](devlooped/moq#1110)) > > * Regression: `mock.Verify[All]` no longer marks invocations as verified if they were matched by conditional setups. (@Lyra2108, [#1114](devlooped/moq#1114)) #Commits - [`74d5863`](devlooped/moq@74d5863) Update version to 4.16.0 - [`424fe31`](devlooped/moq@424fe31) Fix typo in changelog - [`f48c0f4`](devlooped/moq@f48c0f4) Merge pull request [#1126](devlooped/moq#1126) from stakx/setup-task-result - [`6f6a89d`](devlooped/moq@6f6a89d) Update the changelog - [`66bcb21`](devlooped/moq@66bcb21) Enable `task.Result` in delegate-based setup methods - [`42521c4`](devlooped/moq@42521c4) Add ability in `IAwaitableFactory` to create result...
This much more focused version of #1123 only covers setting up the
.Result
of (value) task-based async methods.Benefits
The dedicated async setup methods
.ReturnsAsync
,.ThrowsAsync
etc. are now largely superfluous:From a user perspective, setups become more uniform in shape. From a maintainer's perspective, we have less work. More specifically, we no longer need to ensure that those async setup verbs are at feature parity with their non-async counterparts.
It adds async support where such async verbs aren't currently available:
but also in other places like in
Verify…(callExpression, …)
.It enables recursive setups across async calls in a single setup expression. For example, using just
Mock.Of
:Should
.ReturnsAsync
,.ThrowsAsync
etc. be marked as[Obsolete]
?I am not marking those methods as
[Obsolete]
just yet, mainly for two reasons:There are a few specialized overloads (e.g. for delayed task completion) that would need to be rewritable using just the regular setup verbs. I'd like to look at those separately.
.PassAsync
for sequence setups doesn't have an easy replacement, because non-generic tasks do not have a.Result
property that one could set up instead. Replacing.PassAsync
would require anawait
-like operator substitute (as proposed in Easier async setups through a newAwait(...)
operator #1007 and implemented inAwait
anything & custom awaitable types #1123), which would likely be added together with support for custom awaitable types. Until that happens, it doesn't make sense to deprecate only some (but not all) async setup verbs.What is still missing?
As noted in the new changelog entry, support in
mock.Protected()
is still missing, or at least spotty. Also, unlike #1123, there is no support for custom awaitable types just yet; however, most of the necessary machinery is now in place, so this should be relatively easy to add in the future.Resolves #384, closes #1007, closes #1123.