You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
But Moq doesn't offer anything comparable when async methods come into play.
Say you would like to do the same kind of setup, but instead of using the synchronous property .Child you want to use the .GetChildAsync() method. The most succinct solution currently possible is perhaps this:
which makes use of ReturnsAsync, which—like other ...Async extension methods—tries to make async method setups a little easier. Without those helpers, the solution would be even more elaborate:
Even today, we're still trying to make async methods easier to setup (e.g. by adding more ...Async helper methods, or in #384), but the current approaches don't do anything about async support inside fluent setup expressions. Can something be done about that?
Proposed solution:
Say you would like to do the same kind of setup, but instead of using the synchronous property .Child you want to use the .GetChildAsync() method.
I think the ideal solution would be this:
parentMock.Setup(async p =>(awaitp.GetChildAsync()).Name).Returns("Alice");
Unfortunately, the C# compiler does not allow await in LINQ expression trees.
BUT we could compensate this lack of compiler support with a static helper method Await, which would be used as follows:
This setup expression suggests that the callback should only execute on an await parentMock.Object.GetChildAsync(), but not on a simple execution of parentMock.Object.GetChildAsync() (i.e. without the await). That is, Callback may have to be merged with any Returns present; also, a Callback after Returns might have to be transformed to a task continuation (resultTask.ContinueWith(...)). Not sure how that should go.
I'll shortly begin prototyping this. Comments, questions, and suggestions are welcome!
The text was updated successfully, but these errors were encountered:
stakx
changed the title
Better support for async method through a new Await(...) operator
Easier async setups through a new Await(...) operator
Apr 25, 2020
This feature has essentially made it into the code base; but for now, only task.Result instead of Await(anything) is supported. "Await anything" support may be added in the future.
The discussion below assumes the definition of the following type
IX
and mockparentMock
:Problem:
Today (as of version 4.14.0), Moq has the ability to transparently set up whole object graphs through fluent setup expressions, such as this one:
But Moq doesn't offer anything comparable when async methods come into play.
Say you would like to do the same kind of setup, but instead of using the synchronous property
.Child
you want to use the.GetChildAsync()
method. The most succinct solution currently possible is perhaps this:which makes use of
ReturnsAsync
, which—like other...Async
extension methods—tries to make async method setups a little easier. Without those helpers, the solution would be even more elaborate:Even today, we're still trying to make async methods easier to setup (e.g. by adding more
...Async
helper methods, or in #384), but the current approaches don't do anything about async support inside fluent setup expressions. Can something be done about that?Proposed solution:
I think the ideal solution would be this:
Unfortunately, the C# compiler does not allow
await
in LINQ expression trees.BUT we could compensate this lack of compiler support with a static helper method
Await
, which would be used as follows:which happens to be even shorter than using native C# keywords.
I strongly suspect thatthis is feasible, andthatit would make all existing...Async
helper methods redundant. TakeReturnsAsync
for example:could be rewritten as:
or
ThrowsAsync
:could be rewritten as:
Something that's a little less clear is
Callback
:This setup expression suggests that the callback should only execute on an
await parentMock.Object.GetChildAsync()
, but not on a simple execution ofparentMock.Object.GetChildAsync()
(i.e. without theawait
). That is,Callback
may have to be merged with anyReturns
present; also, aCallback
afterReturns
might have to be transformed to a task continuation (resultTask.ContinueWith(...)
). Not sure how that should go.I'll shortly begin prototyping this. Comments, questions, and suggestions are welcome!
The text was updated successfully, but these errors were encountered: