Sonar Coverage Issue on Async Methods

  • Community Build v25.5.0.107428

I have an asynchronous method that utilizes Polly’s ExecuteAsync and RabbitMQ client’s CreateChannelAsync to establish messaging channels:

    public async Task MethodAsync<T>(T message) where T : IMessage
    {
        await retryPolicy.ExecuteAsync( async () =>
        {
            //Some code

            await Method1Async();

            await using var channel = await connection!.CreateChannelAsync();

            switch ( sth.Type )
            {
                case sth.Type1:
                    await Method1Async( channel );
                    break;
                case sth.Type2:
                    await Method2Async( channel );
                    break;
                case sth.Type3:
                case sth.Type4:
                default:
                    throw new ArgumentOutOfRangeException( nameof( message ), "Invalid" );
            }
        } );
    }

SonarQube reports that the line throw new ArgumentOutOfRangeException(nameof(message), “Invalid”); is only partially covered by tests.

However, I believe all scenarios are accounted for, including the default case, which is tested as follows:

    [Theory]
    [InlineData( sth.Type3)]
    [InlineData( sth.Type4 )]
    [InlineData( (sth)999 )]
    [InlineData( (sth)(-1) )]
    public async Task GivenMethodInvoked_WhenSthTypeIsInvalid_ThenExceptionThrown( sth type)
    {
//some code

            var ex = await Assert.ThrowsAsync<ArgumentOutOfRangeException>( async () => await class.MethodAsync( message ) );
            Assert.Equal( "message", ex.ParamName );
            Assert.Contains( "Invalid", ex.Message );

}

These tests are passing successfully, but I am getting that coverage issue.

And another important point to note:

This method previously passed coverage checks without issue.

Originally, it was a synchronous method, but we introduced asynchronous behavior to accommodate new requirements. The core logic, including the switch statement, remained unchanged - only async/await constructs were added.

The corresponding tests were also updated to reflect these changes. Given that the logic hasn’t changed, I don’t understand why SonarQube now flags the throw new ArgumentOutOfRangeException line as only partially covered.

Is there a known issue with SonarQube when dealing with async methods?

Hello,

Regarding coverage, SonarQube displays results based solely on the coverage report you provide. If certain code is marked as uncovered, it means the underlying coverage report doesn’t recognize it as covered—and SonarQube will reflect that status.

If you notice discrepancies, it’s best to investigate and resolve them with your test or coverage tool, as the issue likely originates there.

If your coverage tool shows the code as covered, come back to us :smiley:

:warning: Only the latest version of SonarQube Community Build is considered active, so you’ll need to update and see if the situation is still replicable before we can help you.

Your update path is:

25.5 → 25.8

You may find these resources helpful:

If you have questions about upgrading, feel free to open a new thread for that here.

If your error persists after update, please come back to us.