Use FakeLogger from framework

This commit is contained in:
Joe DeCock 2025-12-12 07:54:06 -06:00
parent 4444fc6934
commit 0d4f85429f
5 changed files with 10 additions and 60 deletions

View file

@ -82,6 +82,7 @@ that supports the target frameworks our products target (8, 9, 10) -->
<PackageVersion Include="Microsoft.Extensions.Logging" Version="10.0.0" />
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="10.0.0" />
<PackageVersion Include="Microsoft.Extensions.Logging.Console" Version="10.0.0" />
<PackageVersion Include="Microsoft.Extensions.Logging.Testing" Version="10.0.0" />
<PackageVersion Include="Microsoft.Extensions.Options" Version="10.0.0" />
<PackageVersion Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="10.0.0" />
<PackageVersion Include="Microsoft.Extensions.Primitives" Version="10.0.0" />

View file

@ -15,6 +15,7 @@
<PackageReference Include="Duende.IdentityServer" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" />
<PackageReference Include="Microsoft.Extensions.Diagnostics.Testing" />
<PackageReference Include="Meziantou.Extensions.Logging.Xunit" />
<PackageReference Include="Microsoft.Extensions.TimeProvider.Testing" />
<PackageReference Include="RichardSzalay.MockHttp" />

View file

@ -7,9 +7,9 @@ using System.Security.Cryptography;
using System.Text;
using System.Text.Json;
using Duende.AspNetCore.Authentication.JwtBearer.DPoP.TestFramework;
using Duende.AspNetCore.TestFramework;
using Duende.IdentityModel;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.Extensions.Logging.Testing;
using Microsoft.Extensions.Time.Testing;
using Microsoft.IdentityModel.JsonWebTokens;
using Microsoft.IdentityModel.Tokens;
@ -20,25 +20,25 @@ public abstract class DPoPProofValidatorTestBase
{
public DPoPProofValidatorTestBase()
{
Logger = MockLogger.Create();
ExpirationLogger = new FakeLogger<DPoPExpirationValidator>();
Clock = new FakeTimeProvider();
DataProtectionProvider = new EphemeralDataProtectionProvider();
OptionsMonitor = new TestOptionsMonitor<DPoPOptions>(Options);
ExpirationValidator = new DPoPExpirationValidator(
Clock,
Logger.For<DPoPExpirationValidator>());
ExpirationLogger);
NonceValidator = new DefaultDPoPNonceValidator(
OptionsMonitor,
DataProtectionProvider,
Clock,
Logger.For<DefaultDPoPNonceValidator>(),
new FakeLogger<DefaultDPoPNonceValidator>(),
ExpirationValidator);
ProofValidator = new(
OptionsMonitor,
NonceValidator,
ReplayCache,
Clock,
Logger.For<DPoPProofValidator>(),
new FakeLogger<DPoPProofValidator>(),
ExpirationValidator);
var jtiBytes = Encoding.UTF8.GetBytes(TokenId);
TokenIdHash = Base64Url.EncodeToString(SHA256.HashData(jtiBytes));
@ -53,7 +53,7 @@ public abstract class DPoPProofValidatorTestBase
};
}
protected MockLogger Logger { get; }
internal FakeLogger<DPoPExpirationValidator> ExpirationLogger { get; }
protected FakeTimeProvider Clock { get; }
protected IDataProtectionProvider DataProtectionProvider { get; }
protected IDataProtector DataProtector => NonceValidator.DataProtector;

View file

@ -110,7 +110,7 @@ public class FreshnessTests : DPoPProofValidatorTestBase
actual.ShouldBe(expected);
if (expected)
{
Logger.LogMessages.ShouldContain(msg => msg.StartsWith("Expiration check failed. Expiration has already happened."));
ExpirationLogger.Collector.GetSnapshot().ShouldContain(record => record.Message.StartsWith("Expiration check failed. Expiration has already happened."));
}
}
@ -136,7 +136,7 @@ public class FreshnessTests : DPoPProofValidatorTestBase
actual.ShouldBe(expected);
if (expected)
{
Logger.LogMessages.ShouldContain(msg => msg.StartsWith("Expiration check failed. Creation time was too far in the future."));
ExpirationLogger.Collector.GetSnapshot().ShouldContain(record => record.Message.StartsWith("Expiration check failed. Creation time was too far in the future."));
}
}
[Theory]

View file

@ -1,52 +0,0 @@
// Copyright (c) Duende Software. All rights reserved.
// See LICENSE in the project root for license information.
using Microsoft.Extensions.Logging;
namespace Duende.AspNetCore.TestFramework;
public class MockLogger : ILogger
{
public static MockLogger Create() => new MockLogger(new LoggerExternalScopeProvider());
public MockLogger(LoggerExternalScopeProvider scopeProvider) => _scopeProvider = scopeProvider;
public readonly List<string> LogMessages = new();
private readonly LoggerExternalScopeProvider _scopeProvider;
public IDisposable BeginScope<TState>(TState state) where TState : notnull => _scopeProvider.Push(state);
public bool IsEnabled(LogLevel logLevel) => true;
public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func<TState, Exception?, string> formatter) => LogMessages.Add(formatter(state, exception));
/// <summary>
/// Creates a strongly-typed ILogger&lt;T&gt; wrapper that shares the same log messages collection.
/// </summary>
public ILogger<T> For<T>() => new MockLogger<T>(this);
}
public class MockLogger<T> : ILogger<T>
{
private readonly MockLogger _inner;
internal MockLogger(MockLogger inner) => _inner = inner;
public IDisposable BeginScope<TState>(TState state) where TState : notnull => _inner.BeginScope(state);
public bool IsEnabled(LogLevel logLevel) => _inner.IsEnabled(logLevel);
public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func<TState, Exception?, string> formatter)
=> _inner.Log(logLevel, eventId, state, exception, formatter);
}
public class MockLoggerProvider(MockLogger logger) : ILoggerProvider
{
public void Dispose()
{
}
public ILogger CreateLogger(string categoryName) => logger;
}