Skip to content

Verifying Method return value on async methods #228

Open

Description

@JanSdot

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!

Activity

  1. carlreid commented on Jun 13, 2024

    @carlreid

    I think I have achieved this the following way:

    protected readonly IEnumerable<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]
    public void Methods_ThatReturnAwaitableTypes_ShouldHaveAsyncSuffix()
    {
        var rule = 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.

  2. JanSdot commented on Oct 30, 2024

    @JanSdot
    Author

    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.

    [Fact]
    public void Methods_ThatReturnAwaitableTypes_ShouldHaveAsyncSuffix()
    {
        var rule = MethodMembers().That()
                           .AreDeclaredIn(Repositories)
                           .Should()
                           .HaveReturnType(
                                Types().That()
                                .Are(Pocos)
                           );
    
        rule.Check(Architecture);
    }

    Imagining there are the following methods

    public Task<NoPocoObject> GetAsync(){}

    --> ❌ Violation should be found

    public Task<PocoObject> GetAsync(){}

    --> ✅ no Violation should be found (/)

  3. btzdnl commented on Mar 17, 2025

    @btzdnl

    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.

  4. added
    kind/bugCategorizes issue or PR as related to a bug.
    and removed
    kind/supportCategorizes issue or PR as a support question.
    on Apr 25, 2025
  5. alexanderlinne commented on Apr 25, 2025

    @alexanderlinne
    Collaborator

    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.

  6. added
    triage/duplicateIndicates an issue is a duplicate of other open issue.
    triage/acceptedIndicates an issue or PR is ready to be actively worked on.
    and removed
    triage/duplicateIndicates an issue is a duplicate of other open issue.
    on Jun 13, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    kind/bugCategorizes issue or PR as related to a bug.triage/acceptedIndicates an issue or PR is ready to be actively worked on.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions