# यूनिट परीक्षण Umami.Net - ASP में लॉगिंग

# परिचय

मैं मोक का उपयोग करते हुए एक सापेक्ष नोब हूँ।

[TOC]

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

# समस्या

मैं एक साधारण परीक्षण जोड़ने की कोशिश कर रहा था लॉगिन फ़ंक्शन के लिए मैं डेटा खींचते समय उपयोग करने की जरूरत है
जैसा कि आप देख सकते हैं यह' एक सरल सेवा है जो एक उपयोक्ता नाम और पासवर्ड को पास करता है `/api/auth/login` अंतबिंदु और एक परिणाम प्राप्त करता है. यदि परिणाम सफल है तो यह टोकन में भंडारित `_token` क्षेत्र और सेट करता है `Authorization` के लिए शीर्षिका `HttpClient` भविष्य के अनुरोधों में उपयोग करने के लिए

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

अब मैं भी लॉगर के खिलाफ परीक्षण करना चाहता था सुनिश्चित करने के लिए यह सही संदेशों को लॉगिंग करता है `Microsoft.Extensions.Logging` नेमस्पेस और मैं जाँच करना चाहता था कि सही लॉग संदेश लॉगर को लिखा जा रहा है

मोक में परीक्षण लॉगिंग के बारे में पोस्टों का एक बन्च है वे सभी इस मूल रूप को रखते हैं https से (://adamstorr.co\.uk/blog

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

हालांकि मोक के कारण हाल ही में किए गए परिवर्तनों से (It.IsAnyType अब अप्रचलित है।

मैंने संस्करणों और वैकल्पिकों का एक बन्च प्रयास किया लेकिन यह हमेशा असफल रहा।

# समाधान

तो GitHub संदेशों की एक गुच्छा पढ़ते हुए मैं डेविड फोलर द्वारा एक पोस्ट पर आ गया (मेरे पूर्व सहयोगी और अब Lord of .NET) जो ASP में लॉगिंग को परीक्षण करने के लिए एक सरल तरीका दिखाता है
यह उपयोग करता है *मेरे लिए नया* `Microsoft.Extensions.Diagnostics.Testing` [पैकेज](https://github.com/dotnet/extensions/tree/main/src/Libraries/Microsoft.Extensions.Diagnostics.Testing) जो लॉगिंग के परीक्षण के लिए कुछ वास्तव में उपयोगी एक्सटेंशन है

तो सभी मोक सामान के बजाय मैं सिर्फ जोड़ा `Microsoft.Extensions.Diagnostics.Testing` पैकेज और मेरे परीक्षणों में निम्नलिखित जोड़ा.

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

आप' देखेंगे कि यह मेरे सेवा संग्रह सेटअप करता है `FakeLogger<T>` और फिर सेटअप करता है `UmamiData` उपयोक्ता नाम और पासवर्ड के साथ सेवा मैं उपयोग करना चाहता हूँ (ताकि मैं असफलता का परीक्षण कर सकता है

## फेक लॉगगर का प्रयोग करते हुए परीक्षण

तब मेरे परीक्षण हो सकता है

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

जहाँ आप देखेंगे मैं बस कॉल करता हूँ `GetServiceProvider` मेरा सेवा प्रदाता प्राप्त करने के लिए विधि `AuthService` और `ILogger<AuthService>` सेवा प्रदाता से

क्योंकि मैं इन के रूप में सेट किया है `FakeLogger<T>` तब मैं एक्सेस कर सकता हूँ `FakeLogCollector` और `FakeLogRecord` लॉग प्राप्त करने और उन्हें जाँचने के लिए

तब मैं सिर्फ सही संदेश के लिए लॉग जाँच कर सकता हूँ

# अंत में

तो वहाँ आप यह है ',' एक सरल तरीका है कि बिना मोक बेवकूफ के यूनिट परीक्षण में लॉग संदेशों का परीक्षण करने के लिए