diff --git a/azure-pipelines-ci.yml b/azure-pipelines-ci.yml
index 08bd71ee5..4971749b1 100644
--- a/azure-pipelines-ci.yml
+++ b/azure-pipelines-ci.yml
@@ -14,53 +14,45 @@ jobs:
       echo "BuildId = $(buildId)"
     displayName: 'Print buildId'
 
-  - task: UseDotNet@2
-    displayName: Use .NET 8.0
-    inputs:
-      packageType: 'sdk'
-      version: '8.0.x'    
+  - script: |
+      dotnet tool install --global dotnet-sonarscanner
+      dotnet tool install --global dotnet-coverage
+      dotnet tool install --global coverlet.console
+    displayName: 'Install dotnet tools'
 
   - task: PowerShell@2
-    displayName: "Use JDK11 by default"
+    displayName: "Use JDK17 by default"
     inputs:
       targetType: 'inline'
       script: |
-        $jdkPath = $env:JAVA_HOME_11_X64
+        $jdkPath = $env:JAVA_HOME_17_X64
         Write-Host "##vso[task.setvariable variable=JAVA_HOME]$jdkPath"
 
   - script: |
       dotnet dev-certs https --trust || true
     displayName: 'dotnet dev-certs https'
-  
-  - task: SonarCloudPrepare@1
-    displayName: 'Prepare analysis on SonarCloud'
+
+    # See: https://docs.sonarsource.com/sonarcloud/enriching/test-coverage/dotnet-test-coverage
+  - script: |
+      dotnet sonarscanner begin /k:"WireMock-Net_WireMock.Net" /o:"wiremock-net" /d:sonar.branch.name=$(Build.SourceBranchName) /d:sonar.host.url="https://sonarcloud.io" /d:sonar.token="$(SONAR_TOKEN)" /d:sonar.dotnet.excludeTestProjects=true /d:sonar.cs.vscoveragexml.reportsPaths=**/wiremock-coverage.xml /d:sonar.verbose=true
+    displayName: 'Begin analysis on SonarCloud'
     condition: and(succeeded(), ne(variables['Build.Reason'], 'PullRequest')) # Do not run for PullRequests
-    inputs:
-      SonarCloud: SonarCloud
-      organization: wiremock-net
-      projectKey: 'WireMock-Net_WireMock.Net'
-      projectName: 'WireMock.Net'
-      extraProperties: |
-        sonar.cs.opencover.reportsPaths=**/coverage.net8.0.opencover.xml
   
   - task: DotNetCoreCLI@2
     displayName: 'Build Unit tests'
     inputs:
       command: 'build'
       projects: './test/WireMock.Net.Tests/WireMock.Net.Tests.csproj'
-      arguments: '--configuration Debug --framework net8.0'
+      arguments: '--configuration Debug --framework net8.0 --no-incremental'
 
   - task: CmdLine@2
     inputs:
-      script: 'dotnet test ./test/WireMock.Net.Tests/WireMock.Net.Tests.csproj --no-build --configuration Debug --framework net8.0'
+      script: 'dotnet-coverage collect "dotnet test ./test/WireMock.Net.Tests/WireMock.Net.Tests.csproj --configuration Debug --no-build --framework net8.0" -f xml -o "wiremock-coverage.xml"'
     displayName: 'Execute Unit Tests with Coverage'
-   
-  - task: SonarCloudAnalyze@1
-    displayName: 'SonarCloud: Run Code Analysis'
-    condition: and(succeeded(), ne(variables['Build.Reason'], 'PullRequest')) # Do not run for PullRequests
   
-  - task: SonarCloudPublish@1
-    displayName: 'SonarCloud: Publish Quality Gate Result'
+  - script: |
+      dotnet sonarscanner end /d:sonar.token="$(SONAR_TOKEN)"
+    displayName: 'End analysis on SonarCloud'
     condition: and(succeeded(), ne(variables['Build.Reason'], 'PullRequest')) # Do not run for PullRequests
   
   - task: whitesource.ws-bolt.bolt.wss.WhiteSource Bolt@19
diff --git a/test/WireMock.Net.Tests/Extensions/EnumExtensionsTests.cs b/test/WireMock.Net.Tests/Extensions/EnumExtensionsTests.cs
new file mode 100644
index 000000000..ef9fae20b
--- /dev/null
+++ b/test/WireMock.Net.Tests/Extensions/EnumExtensionsTests.cs
@@ -0,0 +1,40 @@
+using System;
+using FluentAssertions;
+using WireMock.Extensions;
+using Xunit;
+
+namespace WireMock.Net.Tests.Extensions;
+
+public class EnumExtensionsTests
+{
+    private enum TestEnum
+    {
+        Value1
+    }
+
+    [Fact]
+    public void EnumExtensions_GetFullyQualifiedEnumValue_ShouldReturnCorrectValue()
+    {
+        // Arrange
+        var enumValue = TestEnum.Value1;
+
+        // Act
+        var result = enumValue.GetFullyQualifiedEnumValue();
+
+        // Assert
+        result.Should().Be("WireMock.Net.Tests.Extensions.TestEnum.Value1");
+    }
+
+    [Fact]
+    public void EnumExtensions_GetFullyQualifiedEnumValue_ShouldThrowArgumentException_WhenTypeIsNotEnum()
+    {
+        // Arrange
+        int nonEnumValue = 42;
+
+        // Act
+        Action act = () => nonEnumValue.GetFullyQualifiedEnumValue();
+
+        // Assert
+        act.Should().Throw<ArgumentException>().WithMessage("T must be an enum");
+    }
+}
\ No newline at end of file