Fix DateTime in Response (#1514)

* Fix DateTime in Response

* // Set the DateTime from the Response to the current DateTime

---------

Co-authored-by: Stef Heyenrath <stef.heyenrath@apg.nl>
This commit is contained in:
Stef HeyenrathandStef Heyenrath authored and GitHub committed 2026-10-07 17:35:58 +02:00
1 parent dd762f218b
commit cb4503b1a6
15 files changed
+90 -21

No files matched your search

@@ -32,7 +32,7 @@ public interface IRequestMessage
string? ProxyUrl { get; set; }
/// <summary>
/// Gets the DateTime.
/// The DateTime when this request was done.
/// </summary>
DateTime DateTime { get; }
@@ -52,7 +52,7 @@ public interface IResponseMessage
object? StatusCode { get; set; }
/// <summary>
/// Gets the DateTime.
/// The DateTime when this response was sent.
/// </summary>
DateTime DateTime { get; }
@@ -0,0 +1,14 @@
// Copyright © WireMock.Net
using System.Diagnostics.CodeAnalysis;
using Microsoft.AspNetCore.Http;
namespace WireMock.Extensions;
internal static class HttpContextExtensions
{
internal static bool TryGet<T>(this HttpContext httpContext, [NotNullWhen(true)] out T? value)
{
return httpContext.Items.TryGetValue(nameof(T), out value);
}
}
@@ -12,7 +12,7 @@ namespace WireMock.Owin.Mappers;
/// <summary>
/// OwinRequestMapper
/// </summary>
internal class OwinRequestMapper : IOwinRequestMapper
internal class OwinRequestMapper(IDateTimeUtils dateTimeUtils) : IOwinRequestMapper
{
/// <inheritdoc />
public async Task<RequestMessage> MapAsync(HttpContext context, IWireMockMiddlewareOptions options)
@@ -72,7 +72,7 @@ internal class OwinRequestMapper : IOwinRequestMapper
await request.HttpContext.Connection.GetClientCertificateAsync()
)
{
DateTime = DateTime.UtcNow
DateTime = dateTimeUtils.UtcNow
};
}
@@ -171,6 +171,12 @@ internal class WireMockMiddleware(
}
finally
{
// Set the DateTime from the Response to the current DateTime
if (response is ResponseMessage responseMessage)
{
responseMessage.DateTime = dateTimeUtils.UtcNow;
}
logger.LogRequestAndResponse(logRequest, request, response, result.Match, result.Partial, activity);
try
@@ -73,20 +73,20 @@ internal class WireMockMiddlewareLogger(
var logEntries = options.LogEntries.ToList();
foreach (var logEntry in logEntries
.OrderBy(le => le.RequestMessage?.DateTime ?? le.ResponseMessage?.DateTime)
.OrderBy(le => le.RequestMessage?.DateTime)
.Take(logEntries.Count - options.MaxRequestLogCount.Value))
{
TryRemoveLogEntry(logEntry);
}
}
// In case RequestLogExpirationDuration has a value greater than 0, try to delete existing request logs based on the date.
// In case RequestLogExpirationDuration has a value greater than 0, try to delete existing request logs based on the RequestMessage date.
if (options.RequestLogExpirationDuration is > 0)
{
var logEntries = options.LogEntries.ToList();
var checkTime = dateTimeUtils.UtcNow.AddHours(-options.RequestLogExpirationDuration.Value);
foreach (var logEntry in logEntries.Where(le => le.RequestMessage?.DateTime < checkTime || le.ResponseMessage?.DateTime < checkTime))
foreach (var logEntry in logEntries.Where(le => le.RequestMessage?.DateTime < checkTime))
{
TryRemoveLogEntry(logEntry);
}
@@ -87,7 +87,7 @@ public partial class Response : IResponseBuilder
{
var message = responseMessage ?? new ResponseMessage
{
DateTime = DateTime.UtcNow // We set it here to the current time.
DateTime = DateTime.UtcNow // Initially, this is set to the current time, but will be updated to the real time once the response has been sent.
};
return new Response(message);
@@ -2,7 +2,6 @@
// This source file is based on mock4net by Alexandre Victoor which is licensed under the Apache 2.0 License.
// For more details see 'mock4net/LICENSE.txt' and 'mock4net/readme.md' in this project root.
using System.Linq;
using Stef.Validation;
using WireMock.ResponseBuilders;
using WireMock.Types;
@@ -0,0 +1,29 @@
// Copyright © WireMock.Net
#if NET6_0_OR_GREATER
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using WireMock.Net.Testcontainers.Utils;
namespace WireMock.Net.Tests.Facts;
[ExcludeFromCodeCoverage]
public sealed class RunOnDockerFact : FactAttribute
{
public RunOnDockerFact(
[CallerFilePath] string? sourceFilePath = null,
[CallerLineNumber] int sourceLineNumber = -1) : base(sourceFilePath, sourceLineNumber)
{
OSPlatform currentPlatform;
try
{
currentPlatform = TestcontainersUtils.GetImageOSAsync.Value.Result;
}
catch
{
Skip = $"Only run test when Docker is installed.";
}
}
}
#endif
@@ -15,7 +15,19 @@ public sealed class RunOnDockerPlatformFact : FactAttribute
[CallerFilePath] string? sourceFilePath = null,
[CallerLineNumber] int sourceLineNumber = -1) : base(sourceFilePath, sourceLineNumber)
{
if (TestcontainersUtils.GetImageOSAsync.Value.Result != OSPlatform.Create(platform))
OSPlatform currentPlatform;
try
{
currentPlatform = TestcontainersUtils.GetImageOSAsync.Value.Result;
}
catch
{
Skip = $"Only run test when Docker is installed.";
return;
}
if (currentPlatform != OSPlatform.Create(platform))
{
Skip = $"Only run test when Docker OS Platform {platform} is used.";
}
@@ -106,6 +106,15 @@ public class WireMockMiddlewareTests
[Fact]
public async Task WireMockMiddleware_Invoke_NoMatch()
{
// Arrange
var inititalDateTime = new DateTime(2027, 1, 1, 0, 0, 0, DateTimeKind.Utc);
var responseDateTime = new DateTime(2027, 1, 1, 0, 0, 42, DateTimeKind.Utc);
_dateTimeUtilsMock.Reset();
_dateTimeUtilsMock.SetupSequence(d => d.UtcNow)
.Returns(inititalDateTime)
.Returns(responseDateTime);
// Act
await _sut.Invoke(_contextMock.Object);
@@ -115,7 +124,7 @@ public class WireMockMiddlewareTests
Expression<Func<ResponseMessage, bool>> match = r =>
(int)r.StatusCode! == 404 &&
((StatusModel)r.BodyData!.BodyAsJson!).Status == "No matching mapping found" &&
r.DateTime == UtcNow;
r.DateTime == responseDateTime;
_responseMapperMock.Verify(m => m.MapAsync(It.Is(match), It.IsAny<HttpResponse>()), Times.Once);
}
@@ -21,7 +21,7 @@ public class TestcontainersTests(ITestOutputHelper testOutputHelper)
TimestampFormat = "yyy-MM-dd HH:mm:ss.fff"
});
[Fact]
[RunOnDockerFact]
public async Task WireMockContainer_Build_And_StartAsync_and_StopAsync()
{
// Act
@@ -57,7 +57,7 @@ public class TestcontainersTests(ITestOutputHelper testOutputHelper)
await StopAsync(wireMockContainer);
}
[Fact]
[RunOnDockerFact]
public async Task WireMockContainer_Build_WithImage_And_StartAsync_and_StopAsync()
{
// Arrange
@@ -83,7 +83,7 @@ public class TestcontainersTests(ITestOutputHelper testOutputHelper)
await StopAsync(wireMockContainer);
}
[Fact]
[RunOnDockerFact]
public async Task WireMockContainer_Build_WithImageAsText_And_StartAsync_and_StopAsync()
{
// Arrange
@@ -10,6 +10,7 @@ using Meziantou.Extensions.Logging.Xunit.v3;
using Microsoft.Extensions.Logging;
using WireMock.Constants;
using WireMock.Net.Testcontainers;
using WireMock.Net.Tests.Facts;
using WireMock.Util;
namespace WireMock.Net.Tests.Testcontainers;
@@ -25,7 +26,7 @@ public class TestcontainersTestsGrpc(ITestOutputHelper testOutputHelper)
TimestampFormat = "yyy-MM-dd HH:mm:ss.fff"
});
[Fact]
[RunOnDockerFact]
public async Task WireMockContainer_Build_Grpc_TestPortsAndUrls1()
{
// Arrange
@@ -82,7 +83,7 @@ public class TestcontainersTestsGrpc(ITestOutputHelper testOutputHelper)
}
}
[Fact]
[RunOnDockerFact]
public async Task WireMockContainer_Build_Grpc_TestPortsAndUrls2()
{
// Arrange
@@ -136,7 +137,7 @@ public class TestcontainersTestsGrpc(ITestOutputHelper testOutputHelper)
}
}
[Fact]
[RunOnDockerFact]
public async Task WireMockContainer_Build_Grpc_ProtoDefinitionFromJson_UsingGrpcGeneratedClient()
{
var wireMockContainer = await Given_WireMockContainerIsStartedForHttpAndGrpcAsync();
@@ -150,7 +151,7 @@ public class TestcontainersTestsGrpc(ITestOutputHelper testOutputHelper)
await StopAsync(wireMockContainer);
}
[Fact]
[RunOnDockerFact]
public async Task WireMockContainer_Build_Grpc_ProtoDefinitionAtServerLevel_UsingGrpcGeneratedClient()
{
var wireMockContainer = await Given_WireMockContainerWithProtoDefinitionAtServerLevelIsStartedForHttpAndGrpcAsync();
@@ -164,7 +165,7 @@ public class TestcontainersTestsGrpc(ITestOutputHelper testOutputHelper)
await StopAsync(wireMockContainer);
}
[Fact]
[RunOnDockerFact]
public async Task WireMockContainer_Build_Grpc_ProtoDefinitionAtServerLevel_UsingGrpcGeneratedClient_AndWithWatchStaticMappings()
{
var wireMockContainer = await Given_WireMockContainerWithProtoDefinitionAtServerLevelWithWatchStaticMappingsIsStartedForHttpAndGrpcAsync();
@@ -18,6 +18,7 @@ using WireMock.Util;
namespace WireMock.Net.Tests;
[Collection(nameof(WireMockServerProxyTests))]
public class WireMockServerProxyTests
{
private readonly CancellationToken _ct = TestContext.Current.CancellationToken;
@@ -46,5 +46,3 @@ public class WireMockServerProxy2Tests
serverAsProxy.Dispose();
}
}