NFluent: Check.ThatCode for Task-returning methods does not await result in 3.0.0
Bug Type
Please pick one:
- a check failed to detect an error (false negative), i.e. a test is green while it should be red.
- a check raised un existing error (false positive), i.e a test is red while it should be green.
- an error message is invalid/incomplete (please provide samples)
- a ran into an exception.
- other.
Describe the bug
I’m upgrading from 2.7.2 to 3.0.0 and have found I had to migrate .ThatAsyncCode
to .ThatCode
since the former is Obsolete and I treat warnings as errors. https://www.nuget.org/packages/NFluent/3.0.0.351#readme-body-tab advises that this should replace it (“ThatAsyncCode: you can now use ThatCode even for async methods”)
However, unlike .ThatAsyncCode in the earlier version, .ThatCode does not await the Task for non-generic Task-returning, non-async methods. (However it works fine for Task<T>
-returning non-async methods, and also for async methods returning Task
).
To Reproduce
[Test]
public void Async_issue()
{
// simulates the code under test
async Task<bool> PleaseThrowAsync()
{
await Task.Yield();
throw new InvalidOperationException("Oh dear!)");
}
async Task PleaseThrowAsync2()
{
await Task.Yield();
throw new InvalidOperationException("Oh dear!)");
}
// assert
// #1 lambda is async method returning Task<T>:
Check.ThatCode(async () => await PleaseThrowAsync()).Throws<InvalidOperationException>();
// #2 lambda is non-async method returning Task<T>:
Check.ThatCode(() => PleaseThrowAsync()).Throws<InvalidOperationException>();
// #3 lambda is async method returning Task:
Check.ThatCode(async () => await PleaseThrowAsync2()).Throws<InvalidOperationException>();
// #4 lambda is non-async method returning Task:
Check.ThatCode(() => PleaseThrowAsync2()).Throws<InvalidOperationException>();
}
This throws on the 4th and final Check.ThatCode
. For now I can explicitly make the lambda async (ie transform code like check 4 to code like check 3), but I don’t think this is expected to be required.
The equivalent code in 2.7.2 (using ThatAsyncCode
instead of ThatCode
) does not fail. I encountered this problem when I did a global replace of ThatAsyncCode with ThatCode upon upgrading.
I note that ThatCode<TU>(Func<Task<TU>> awaitableFunc)
calls RunTrace.GetAsyncTrace
, while ThatCode(Func<Task> awaitableFunc)
does not (it calls RunTrace.GetTrace
. which then explicitly checks whether the method is async by inspecting whether it has an AsyncStateMachineAttribute). This explains why it works for check 2 but not check 4. Perhaps the fix is simply to change this method to use GetAsyncTrace?
Under the earlier version, ThatAsyncCode(Func<Task> awaitableMethod)
called GetAsyncTrace
, which explains why it used to work.
Expected behavior Test code above should not fail, and certainly cases 2 and 4 should not be inconsistent.
Desktop (please complete the following information):
- NFluent version: 3.0.0
- Net Version: fwk 4.8.2
- IDE: Rider
About this issue
- Original URL
- State: closed
- Created a year ago
- Comments: 18
Commits related to this issue
- fix: issue #339 — committed to tpierrain/NFluent by dupdob a year ago
- fix: issue #339 — committed to tpierrain/NFluent by dupdob a year ago
- fix: issue #339 — committed to NFluent/NFluent by dupdob a year ago
Yep, I am still into this. I may have a way to keep signatures this way, but you are right, it definitely makes more sense to assume Task returning methods are
async
in nature. I am just looking for a way to check forTask Factory
methods.Long story short, I may have to reintroduce Check.ThatAsyncCode