TNG / ArchUnitNET

A C# architecture test library to specify and assert architecture rules in C# for automated testing.
Apache License 2.0
915 stars 60 forks source link

Verifying Method return value on async methods #228

Open JanSdot opened 8 months ago

JanSdot commented 8 months ago

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!

carlreid commented 5 months ago

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.

JanSdot commented 2 weeks ago

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(){}

--> :x: Violation should be found

public Task<PocoObject> GetAsync(){}

--> :white_check_mark: no Violation should be found (/)