Back to "Yksikön testaus Umami.Net - ASP:n Logging in .NET Core"

This is a viewer only at the moment see the article on how this works.

To update the preview hit Ctrl-Alt-R (or ⌘-Alt-R on Mac) or Enter to refresh. The Save icon lets you save the markdown file to disk

This is a preview from the server running through my markdig pipeline

ASP.NET Core xUnit

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

Wednesday, 04 September 2024

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.

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ä.

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

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 , 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.

    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:

    [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

logo

© 2026 Scott Galloway — Unlicense — All content and source code on this site is free to use, copy, modify, and sell.