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
{{ message }}
Repository navigation
Verifying Method return value on async methods #228
Maybe I just don't know how to do it, but for me it seems that it is right now not possible to verify return parameters of a method, if that method is async, so actually return a Task<TReturn> where there Return is what you actually want to check.
It would be great if this would be added or a hint how this could be accomplished!
Great framework by the way!
Reacted by Daniel Betz, Will Baldoumas, Tim Paulus and Stijn Herreman
protectedreadonlyIEnumerable<System.Type>AwaitableTypes=[typeof(Task),typeof(Task<>),typeof(ValueTask),typeof(ValueTask<>)];/// <summary>/// Methods returning <see cref="Task"/>, <see cref="Task{TResult}"/>, <see cref="ValueTask"/>, <see cref="ValueTask{TResult}"/>/// should have names that end with "Async"./// <see href="https://learn.microsoft.com/en-us/dotnet/csharp/asynchronous-programming/task-asynchronous-programming-model#BKMK_NamingConvention">Naming Convention for Async Methods</see>/// </summary>[Fact]publicvoidMethods_ThatReturnAwaitableTypes_ShouldHaveAsyncSuffix(){varrule=MethodMembers().That().HaveReturnType(AwaitableTypes).Should().HaveNameContaining("Async(");rule.Check(Architecture);}
I wanted to use .HaveNameEndingWith("Async");, but I think that might be checking the method name, plus arguments. For instance ExecuteAsync(bool something) is flagging up as a failure. Though with .HaveNameContaining("Async("); it passes.
It’s not just about Task<T> either. Returning anything that wraps the type interferes with the check, including all generic collection types. Sure you could allow certain wrapper types, but where does it end? You can’t really allow them by default either, because they may actually be unacceptable.
If you take the reverse approach, like making sure forbidden types do not escape, it only gets worse, because then you get false negatives: Even though a forbidden type leaks, the tests don’t catch it.
Maybe we need MethodMembers().Should().NotHaveReturnTypeThat().DependsOnAny(…) and the like. Also, these must check the ITypeInstance because generic arguments actually matter.
Thank you for reporting this. I will need some more time to evaluate this, but I think it would make most sense to remove ITypeInterface and merge it's fields into IType, especially since we are looking at replacing Mono.Cecil with System.Reflection. As far as I've had a look at it, this may impact performance slightly since there are more instances of IType that would need to be evaluated, but also all generics and their instances would be available for matching. This should also allow implementing this use case, because generic arguments are no longer ignored.
Activity
carlreid commentedon Jun 13, 2024
I think I have achieved this the following way:
I wanted to use
.HaveNameEndingWith("Async");, but I think that might be checking the method name, plus arguments. For instanceExecuteAsync(bool something)is flagging up as a failure. Though with.HaveNameContaining("Async(");it passes.JanSdot commentedon Oct 30, 2024
I think there was a misunderstanding. I do not want to check that the method is named Async, but that it is returning a special type of type.
Imagining there are the following methods
--> ❌ Violation should be found
--> ✅ no Violation should be found (/)
btzdnl commentedon Mar 17, 2025
It’s not just about
Task<T>either. Returning anything that wraps the type interferes with the check, including all generic collection types. Sure you could allow certain wrapper types, but where does it end? You can’t really allow them by default either, because they may actually be unacceptable.If you take the reverse approach, like making sure forbidden types do not escape, it only gets worse, because then you get false negatives: Even though a forbidden type leaks, the tests don’t catch it.
Maybe we need
MethodMembers().Should().NotHaveReturnTypeThat().DependsOnAny(…)and the like. Also, these must check theITypeInstancebecause generic arguments actually matter.alexanderlinne commentedon Apr 25, 2025
Thank you for reporting this. I will need some more time to evaluate this, but I think it would make most sense to remove
ITypeInterfaceand merge it's fields intoIType, especially since we are looking at replacingMono.CecilwithSystem.Reflection. As far as I've had a look at it, this may impact performance slightly since there are more instances ofITypethat would need to be evaluated, but also all generics and their instances would be available for matching. This should also allow implementing this use case, because generic arguments are no longer ignored.