# Unit Testing Umami .. .Net Logging im ASP ,. .NET Core

# Einleitung

Ich bin ein relativer Noob, der Moq benutzt und Moq verwendet.(.Yes IM'.m sich der Kontroversen bewusst ist und ich habe versucht, einen neuen Service zu testen.IM'.m hinzufügen, um Umami.....Net.,.umamiData.MSC7. Dies ist ein Dienst, mit dem ich Daten aus meiner Umami-Instanz ziehen kann, um in Sachen wie die Sortierung von Posts durch Popularität usw. zu verwenden.

[TOC]

<!--category-- xUnit, ASP.NET Core -->
<datetime class="hidden">2024-09-04T13:22</datetime>

# Das Problem

Ich habe versucht, einen einfachen Test für die Login-Funktion hinzuzufügen, die ich beim Ziehen von Daten verwenden muss.
Wie Sie es sehen können, ist ein einfacher Dienst, der einen Benutzernamen und Passwort an die `/api/auth/login` Endpoint und bekommt ein Ergebnis...... Wenn das Ergebnis erfolgreich ist, speichert es den Token in der `_token` Feld und setzt die `Authorization` Kopfzeile für die `HttpClient` in zukünftigen Anfragen zu verwenden

```csharp
public class AuthService(HttpClient httpClient, UmamiDataSettings umamiSettings, ILogger<AuthService> logger)
{
    private string _token = string.Empty;
    public HttpClient HttpClient => httpClient;

    public async Task<bool> LoginAsync()
    {
        var loginData = new
        {
            username = umamiSettings.Username,
            password = umamiSettings.Password
        };

        var content = new StringContent(JsonSerializer.Serialize(loginData), Encoding.UTF8, "application/json");
        var response = await httpClient.PostAsync("/api/auth/login", content);

        if (response.IsSuccessStatusCode)
        {
            var authResponse = await response.Content.ReadFromJsonAsync<AuthResponse>();

            if (authResponse == null)
            {
                logger.LogError("Login failed");
                return false;
            }

            _token = authResponse.Token;
            httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", _token);
            logger.LogInformation("Login successful");
            return true;
        }

        logger.LogError("Login failed");
        return false;
    }
}
```

Nun wollte ich auch gegen den Logger testen, um sicherzustellen, dass es die korrekte messages logging. `Microsoft.Extensions.Logging` namespace und ich wollten testen, dass die richtigen Log-Nachrichten auf den Logger geschrieben wurden.

In Moq gibt es ein BUNCH der Pfosten um das Testen des Loggings sie alle haben diese grundlegende Form ( von https-://-adamstorr..-co-.-uk-MSC5-blogs-Mocking--ilogger.- mit --moq-MS K10

```csharp
public static Mock<ILogger<T>> VerifyDebugWasCalled<T>(this Mock<ILogger<T>> logger, string expectedMessage)
{
    Func<object, Type, bool> state = (v, t) => v.ToString().CompareTo(expectedMessage) == 0;
    
    logger.Verify(
        x => x.Log(
            It.Is<LogLevel>(l => l == LogLevel.Debug),
            It.IsAny<EventId>(),
            It.Is<It.IsAnyType>((v, t) => state(v, t)),
            It.IsAny<Exception>(),
            It.Is<Func<It.IsAnyType, Exception, string>>((v, t) => true)));

    return logger;
}
```

WIE auch immer aufgrund von Moq-' , die jüngsten Änderungen ,( ,It , . , IsAnyType ist jetzt obsolet , und ASP-. ,NET Core , ' , Änderungen in FormattedLogValues Ich hatte eine harte Zeit bekommen diese zu arbeiten , um . ,

Ich versuchte ein BUNCH von Versionen und Varianten, aber es immer fehlgeschlagen , . , So ,... , ich gab auf , . ,

# Die Lösung

So las ich eine Reihe von GitHub Nachrichten, die ich auf einen Beitrag von David Fowler stieß.('my ehemaliger Kollege und jetzt der Herr von -. ,NET ,)' was zeigte einen einfachen Weg zum Testen der Protokollierung in ASP , . , NET Core , .'
Dabei wird die *neu für mich* `Microsoft.Extensions.Diagnostics.Testing` [Verpackung](https://github.com/dotnet/extensions/tree/main/src/Libraries/Microsoft.Extensions.Diagnostics.Testing) welche einige wirklich nützliche Erweiterungen für das Testen des Loggings hat

Also statt all dem Moq Zeug habe ich gerade die `Microsoft.Extensions.Diagnostics.Testing` Paket und fügte hinzu, dass die folgenden zu meinen Tests

```csharp
    public IServiceProvider GetServiceProvider (string username="username", string password="password")
    {
        var services = new ServiceCollection();
        var mockLogger = new FakeLogger<UmamiDataService>();
        var authLogger = new FakeLogger<AuthService>();
        services.AddScoped<ILogger<UmamiDataService>>(_ => mockLogger);
        services.AddScoped<ILogger<AuthService>>(_ => authLogger);
        services.SetupUmamiData(username, password);
        return  services.BuildServiceProvider();
        
    }
```

Sie sehen, dass dieses meine ServiceCollection aufstellt. `FakeLogger<T>` und stellt dann die `UmamiData` service mit dem Benutzernamen und Passwort Ich möchte verwenden, um (.so kann ich Testfehler.)..

## Die Tests mit FakeLogger

Dann können meine Tests werden.

```csharp
    [Fact]
    public async Task SetupTest_Good()
    {
        var serviceProvider = GetServiceProvider();
        var authService = serviceProvider.GetRequiredService<AuthService>();
        var authLogger = serviceProvider.GetRequiredService<ILogger<AuthService>>();
        var result = await authService.LoginAsync();
        var fakeLogger = (FakeLogger<AuthService>)authLogger;
        FakeLogCollector collector = fakeLogger.Collector; // Collector allows you to access the captured logs
         IReadOnlyList<FakeLogRecord> logs = collector.GetSnapshot();
         Assert.Contains("Login successful", logs.Select(x => x.Message));
        Assert.True(result);
    }
```

Wo du siehst, rufe ich einfach die `GetServiceProvider` Methode, um meinen Service-Provider zu erhalten. `AuthService` und `ILogger<AuthService>` von dem Dienstleister

Weil ich diese als `FakeLogger<T>` Ich kann dann auf die `FakeLogCollector` und `FakeLogRecord` um die Protokolle zu erhalten und sie zu überprüfen

Dann kann ich einfach die Protokolle nach den richtigen Nachrichten überprüfen.

# Schlussfolgerung

So dort haben Sie es.,... eine einfache Möglichkeit, Protokollmeldungen in Unit Tests ohne den Moq-Unsinn zu testen.