From 0439469f248cafdb60fce91ba79ccfcd1f7068e2 Mon Sep 17 00:00:00 2001 From: Mark Ridgwell <273118822+dnyw4l3n13@users.noreply.github.com> Date: Mon, 22 Jun 2026 11:06:34 +0000 Subject: [PATCH 1/2] test(discord): Add null-guard branch coverage for BotService constructor Adds a reflection-based test to cover the null-bot argument guard in BotService, bringing BotService to 100% line and branch coverage. The null! operator cannot be used directly due to the NX0002 analyser rule, so the constructor is invoked via reflection. Prompt: Work on issue #356 in funfair-tech/BuildBot. Closes #356 --- CHANGELOG.md | 1 + .../Services/BotServiceTests.cs | 15 +++++++++++++++ 2 files changed, 16 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 54f60b33..9b022b13 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ Please ADD ALL Changes to the UNRELEASED SECTION and not a specific release - BuildBot.Json.Tests: new test project covering BuildBot.Json at 100% line and branch coverage - BuildBot.ServiceModel.Tests: Added test coverage for all types in BuildBot.ServiceModel - BuildBot.Discord.Tests: Added unit tests to increase code coverage to 100% +- BotService null-guard branch coverage test ### Fixed - Suppress known Scriban 6.2.0 vulnerabilities pending upgrade - SnsMessage: Token property was never populated from the constructor argument diff --git a/src/BuildBot.Discord.Tests/Services/BotServiceTests.cs b/src/BuildBot.Discord.Tests/Services/BotServiceTests.cs index 426952cc..ef5ba1e7 100644 --- a/src/BuildBot.Discord.Tests/Services/BotServiceTests.cs +++ b/src/BuildBot.Discord.Tests/Services/BotServiceTests.cs @@ -1,4 +1,5 @@ using System; +using System.Reflection; using System.Threading; using System.Threading.Tasks; using BuildBot.Discord.Models; @@ -105,4 +106,18 @@ await bot.Received(1) ); } } + + [Fact] + public void Constructor_ThrowsArgumentNullException_WhenBotIsNull() + { + MessageChannel messageChannel = new(); + MessageChannel releaseChannel = new(); + + ConstructorInfo ctor = Assert.Single(typeof(BotService).GetConstructors()); + + TargetInvocationException ex = Assert.Throws(() => + ctor.Invoke([null, messageChannel, releaseChannel]) + ); + Assert.IsType(ex.InnerException); + } } From b04c00f7f0cfb434c358d79561687ab63ad34625 Mon Sep 17 00:00:00 2001 From: Mark Ridgwell <273118822+dnyw4l3n13@users.noreply.github.com> Date: Tue, 23 Jun 2026 16:23:17 +0000 Subject: [PATCH 2/2] refactor(test): strengthen BotService null-guard constructor test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Use GetConstructor with explicit parameter types instead of Assert.Single on GetConstructors(), avoiding confusing failure messages if a second constructor is ever added - Remove unnecessary MessageChannel allocations — the constructor throws before touching the channel parameters, so null suffices for those args - Assert ParamName == "bot" on the caught ArgumentNullException so a mis-targeted guard is detected rather than silently passing Prompt: Work on pull request #377 in funfair-tech/BuildBot. --- .../Services/BotServiceTests.cs | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/BuildBot.Discord.Tests/Services/BotServiceTests.cs b/src/BuildBot.Discord.Tests/Services/BotServiceTests.cs index ef5ba1e7..97fb6976 100644 --- a/src/BuildBot.Discord.Tests/Services/BotServiceTests.cs +++ b/src/BuildBot.Discord.Tests/Services/BotServiceTests.cs @@ -110,14 +110,13 @@ await bot.Received(1) [Fact] public void Constructor_ThrowsArgumentNullException_WhenBotIsNull() { - MessageChannel messageChannel = new(); - MessageChannel releaseChannel = new(); - - ConstructorInfo ctor = Assert.Single(typeof(BotService).GetConstructors()); - - TargetInvocationException ex = Assert.Throws(() => - ctor.Invoke([null, messageChannel, releaseChannel]) + ConstructorInfo? ctor = typeof(BotService).GetConstructor( + [typeof(IDiscordBot), typeof(IMessageChannel), typeof(IMessageChannel)] ); - Assert.IsType(ex.InnerException); + Assert.NotNull(ctor); + + TargetInvocationException ex = Assert.Throws(() => ctor.Invoke([null, null, null])); + ArgumentNullException ane = Assert.IsType(ex.InnerException); + Assert.Equal(expected: "bot", actual: ane.ParamName); } }