Skip to content

Commit

Permalink
Added Tests for CorrelationId in the Http package, Added HttpContext …
Browse files Browse the repository at this point in the history
…Customization in the Testing package.

(#description: Added Tests for CorrelationId in the Http package, Added HttpContext Customization in the Testing package)
  • Loading branch information
Farshad DASHTI authored and Farshad DASHTI committed Oct 8, 2024
1 parent 0691c13 commit 5725a92
Show file tree
Hide file tree
Showing 7 changed files with 175 additions and 18 deletions.
1 change: 0 additions & 1 deletion .github/workflows/build-test-http.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,5 @@ jobs:
with:
project_name: DfE.CoreLibs.Http
project_path: src/DfE.CoreLibs.Http
run_tests: false
secrets:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
9 changes: 8 additions & 1 deletion DfE.CoreLibs.sln
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DfE.CoreLibs.AsyncProcessin
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{3F89DCAD-8EC7-41ED-A08F-A9EFAE263EB4}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DfE.CoreLibs.Utilities.Tests", "src\Tests\DfE.CoreLibs.Utilities.Tests\DfE.CoreLibs.Utilities.Tests.csproj", "{07AE8F19-9566-4F0C-92E6-0A2BF122DCC9}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DfE.CoreLibs.Utilities.Tests", "src\Tests\DfE.CoreLibs.Utilities.Tests\DfE.CoreLibs.Utilities.Tests.csproj", "{07AE8F19-9566-4F0C-92E6-0A2BF122DCC9}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DfE.CoreLibs.Http.Tests", "src\Tests\DfE.CoreLibs.Http.Tests\DfE.CoreLibs.Http.Tests.csproj", "{69529D73-DD34-43A2-9D06-F3783F68F05C}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Expand Down Expand Up @@ -53,12 +55,17 @@ Global
{07AE8F19-9566-4F0C-92E6-0A2BF122DCC9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{07AE8F19-9566-4F0C-92E6-0A2BF122DCC9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{07AE8F19-9566-4F0C-92E6-0A2BF122DCC9}.Release|Any CPU.Build.0 = Release|Any CPU
{69529D73-DD34-43A2-9D06-F3783F68F05C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{69529D73-DD34-43A2-9D06-F3783F68F05C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{69529D73-DD34-43A2-9D06-F3783F68F05C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{69529D73-DD34-43A2-9D06-F3783F68F05C}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{07AE8F19-9566-4F0C-92E6-0A2BF122DCC9} = {3F89DCAD-8EC7-41ED-A08F-A9EFAE263EB4}
{69529D73-DD34-43A2-9D06-F3783F68F05C} = {3F89DCAD-8EC7-41ED-A08F-A9EFAE263EB4}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {01D11FBC-6C66-43E4-8F1F-46B105EDD95C}
Expand Down
6 changes: 5 additions & 1 deletion src/DfE.CoreLibs.Http/Middlewares/CorrelationId/Keys.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
namespace DfE.CoreLibs.Http.Middlewares.CorrelationId;
using System.Runtime.CompilerServices;

[assembly: InternalsVisibleTo("DfE.CoreLibs.Http.Tests")]

namespace DfE.CoreLibs.Http.Middlewares.CorrelationId;

/// <summary>
/// The keys used by the correlation id middleware.
Expand Down
15 changes: 0 additions & 15 deletions src/DfE.CoreLibs.Http/ReleaseNotes.md

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using AutoFixture;
using Microsoft.AspNetCore.Http;

namespace DfE.CoreLibs.Testing.AutoFixture.Customizations
{
public class HttpContextCustomization : ICustomization
{
public void Customize(IFixture fixture)
{
fixture.Register(() => new DefaultHttpContext());
}
}
}
30 changes: 30 additions & 0 deletions src/Tests/DfE.CoreLibs.Http.Tests/DfE.CoreLibs.Http.Tests.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>

<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="coverlet.collector" Version="6.0.0" />
<PackageReference Include="FluentAssertions" Version="6.12.1" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
<PackageReference Include="NSubstitute" Version="5.1.0" />
<PackageReference Include="xunit" Version="2.5.3" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.3" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\DfE.CoreLibs.Http\DfE.CoreLibs.Http.csproj" />
<ProjectReference Include="..\..\DfE.CoreLibs.Testing\DfE.CoreLibs.Testing.csproj" />
</ItemGroup>

<ItemGroup>
<Using Include="Xunit" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
using AutoFixture;
using AutoFixture.Xunit2;
using DfE.CoreLibs.Http.Interfaces;
using DfE.CoreLibs.Http.Middlewares.CorrelationId;
using DfE.CoreLibs.Testing.AutoFixture.Attributes;
using DfE.CoreLibs.Testing.AutoFixture.Customizations;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using NSubstitute;
using System.Net;

namespace DfE.CoreLibs.Http.Tests.Middlewares
{
public class CorrelationIdMiddlewareTests
{
private readonly RequestDelegate _nextDelegate;
private readonly ILogger<CorrelationIdMiddleware> _logger;
private readonly ICorrelationContext _correlationContext;
private readonly CorrelationIdMiddleware _middleware;

public CorrelationIdMiddlewareTests()
{
_nextDelegate = Substitute.For<RequestDelegate>();
_logger = Substitute.For<ILogger<CorrelationIdMiddleware>>();
_correlationContext = Substitute.For<ICorrelationContext>();
_middleware = new CorrelationIdMiddleware(_nextDelegate, _logger);
}

[Theory]
[CustomAutoData(typeof(HttpContextCustomization))]
public async Task Invoke_ShouldSetNewCorrelationId_WhenHeaderNotPresent(
HttpContext context)
{
// Arrange
context.Request.Headers.Remove(Keys.HeaderKey);
context.Response.Body = new System.IO.MemoryStream();

_nextDelegate.Invoke(context).Returns(Task.CompletedTask);

// Act
await _middleware.Invoke(context, _correlationContext);

// Assert
Assert.True(Guid.TryParse(context.Response.Headers[Keys.HeaderKey], out var correlationId));
Assert.NotEqual(Guid.Empty, correlationId);
_correlationContext.Received(1).SetContext(Arg.Any<Guid>());
}

[Theory]
[CustomAutoData(typeof(HttpContextCustomization))]
public async Task Invoke_ShouldRetainExistingCorrelationId_WhenHeaderPresent([Frozen] IFixture fixture,
DefaultHttpContext context)
{
// Arrange
var existingCorrelationId = fixture.Create<Guid>();
context.Request.Headers[Keys.HeaderKey] = existingCorrelationId.ToString();
context.Response.Body = new System.IO.MemoryStream();

_nextDelegate.Invoke(context).Returns(Task.CompletedTask);

// Act
await _middleware.Invoke(context, _correlationContext);

// Assert
Assert.Equal(existingCorrelationId.ToString(), context.Response.Headers[Keys.HeaderKey]);
_correlationContext.Received(1).SetContext(existingCorrelationId);
}

[Theory]
[CustomAutoData(typeof(HttpContextCustomization))]
public async Task Invoke_ShouldReturnBadRequest_WhenCorrelationIdIsEmpty(DefaultHttpContext context)
{
// Arrange
context.Request.Headers[Keys.HeaderKey] = Guid.Empty.ToString();
context.Response.Body = new System.IO.MemoryStream();

_nextDelegate.Invoke(context).Returns(Task.CompletedTask);

// Act
await _middleware.Invoke(context, _correlationContext);

// Assert
Assert.Equal((int)HttpStatusCode.BadRequest, context.Response.StatusCode);
Assert.Contains("Bad Request", ReadResponseBody(context));
_correlationContext.DidNotReceive().SetContext(Arg.Any<Guid>());
}

[Theory]
[CustomAutoData(typeof(HttpContextCustomization))]
public async Task Invoke_ShouldLogNewGuidWarning_WhenHeaderCannotBeParsed(DefaultHttpContext context)
{
// Arrange
context.Request.Headers[Keys.HeaderKey] = "invalid-guid";
context.Response.Body = new System.IO.MemoryStream();

_nextDelegate.Invoke(context).Returns(Task.CompletedTask);

// Act
await _middleware.Invoke(context, _correlationContext);

// Assert
_logger.Received(1).Log(
LogLevel.Warning,
Arg.Any<EventId>(),
Arg.Is<object>(v => v.ToString().Contains("Detected header x-correlationId, but value cannot be parsed to a GUID")),
Arg.Any<Exception>(),
Arg.Any<Func<object, Exception, string>>()!);

_correlationContext.Received(1).SetContext(Arg.Any<Guid>());
}

private static string ReadResponseBody(HttpContext context)
{
context.Response.Body.Seek(0, System.IO.SeekOrigin.Begin);
using var reader = new System.IO.StreamReader(context.Response.Body);
return reader.ReadToEnd();
}
}
}

0 comments on commit 5725a92

Please sign in to comment.