# Yksikön testaus Umami.Net - ASP:n Logging in .NET Core

# Esitys

I'niin suhteellinen noob, joka käyttää Moq-järjestelmää (kyllä I 'nii tietoinen ristiriitaisuuksistaM SK3 ja pyrin testaamaan uutta palvelua I'niitän UmamiinMST5NetMSV6UmamiDataMSP7 Tämä on palvelu, jonka avulla voin vetää tietoja omalta Umami instancelta, jota voin käyttää asioissa kuten populariteetin ja muiden vastaavien mainintojen sortoinnissa.

[TOC]

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

# Ongelma

Yritin lisätä yksinkertaisen testin, joka koskee sitä login-toimintoa, jota minun on käytettävä tietojen vetämisessä.
Kuten voitte nähdä, ' on yksinkertainen palvelu, joka siirtää käyttäjänamen ja -passin `/api/auth/login` loppupiste ja saa tuloksen. Jos tulos on onnistunut, se tallentaa token `_token` ja asettaa `Authorization` otsikko `HttpClient` käytettäviksi tulevissa pyyntöissä.

```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;
    }
}
```

Nyt halusin myös testata logaria sen varmistamiseksi, että se kirjaa oikeat viestit. IM SK1m käyttäen `Microsoft.Extensions.Logging` namespace ja halusin testata, että oikeat logiviestit kirjoitetaan logiin.

Moqissa on ”'”-osoitteita, jotka koskevat testausloggingia, ja niillä kaikilla on tämä perusmuoto: ( https://://adamstorr .co.uk/blogMST6mockingMst7iloggerM st8withMSt9moqMrst10

```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;
}
```

Mutta Moq:n viimeaikaisten muutosten vuoksi (, It, . ja IsAnyType ovat nyt vanhentuneita.

Olen yrittänyt monenlaisia versioita, mutta ne ovat aina epäonnistuneet.

# Ratkaisu

Näin ollen lukiessani joitakin GitHubin viestejä törmäsin David Fowlerin postiin ( entisestä kollegastani ja nyt Lord of .NET), jossa esitettiin yksinkertainen tapa testata ASP:n tilaamista.
Siinä käytetään *uusi minulle* `Microsoft.Extensions.Diagnostics.Testing` [paketti](https://github.com/dotnet/extensions/tree/main/src/Libraries/Microsoft.Extensions.Diagnostics.Testing) , jolla on joitakin todella hyödyllisiä lisäyksiä logauksen testaamiseksi.

Sen sijaan, että lisäisin kaikki Moq-asiat `Microsoft.Extensions.Diagnostics.Testing` ja lisättiin seuraavat testini kohtaan.

```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();
        
    }
```

Huomaatte, että tämä asettaa palveluniCollectionin. `FakeLogger<T>` ja sen jälkeen perustaa `UmamiData` palvelu, johon sisältyy käyttäjänimi ja -tunnus, jota haluan käyttää (niten voin testata epäonnistumisen

## Testit FakeLoggerin avulla

Silloin testini voivat olla:

```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);
    }
```

Kun näette, kutsun yksinkertaisesti `GetServiceProvider` menetelmä saada palveluntarjoajaani, ja sitten saada `AuthService` ja `ILogger<AuthService>` palveluntarjoajalta.

Koska minulla on nämä järjestelmät `FakeLogger<T>` Voin sitten käyttää `FakeLogCollector` ja `FakeLogRecord` saada pöytäkirjat ja tarkistaa ne.

Sen jälkeen voin vain tarkistaa pöytäkirjat oikeista viesteistä.

# Päätelmissä

Näin ollen teillä on se, yksinkertainen tapa testata pöytäkirjan viestejä yksiköiden testeissä Moq-järjettömyyden välttämättömällä tavalla