Umami.Net MS K1测试UmmiClient单位测试 (中文 (Chinese Simplified))

Umami.Net MS K1测试UmmiClient单位测试

Sunday, 01 September 2024

//

4 minute read

一. 导言导言 导言 导言 导言

现在我有了 Ummami.+Net 套件 我当然希望确保一切工作都如预期的那样有效 . 这样做的最好方法就是全面测试所有的方法和等级 注意: 这是'}这是'}这不是一个“MSK2”的完美方法'}{,}_BARBAR_MSK IHttpMessageHandler a 在这里您可以攻击一位女主人 Handler 成为普通的 HttpClient 来做这个 .}我只是想展示你如何用一个 Mok. 来做到这一点。

单位测试

单位测试是指单个编码单位的测试过程,以确保它们如预期的那样工作。 这是通过写作检测完成的,用控制的方式将方法和等级调用起来,然后按照预期检查输出=.}

对于像 UmamiMSMK0}Net 这样的软件包来说,当它同时调用远程客户端时,这是一个多么棘手的问题。 HttpClient 并且有一个 IHostedService 它用来使新事件数据的发送尽可能无缝\ .

UmamiClient测试

试验的主要部分a HttpClient 新建库正在避免实际的 @' @HttpClient@'}拨号: .}这样可以创建 HttpClient 使用 a HttpMessageHandler 返回已知响应@.} 这将通过创建 HttpClient 与 a 有 HttpMessageHandler 返回已知的响应@;}在此情况下,我只回回输入回复并检查是否没有被 UmamiClient.

    public static HttpMessageHandler Create()
    {
        var mockHandler = new Mock<HttpMessageHandler>();

        mockHandler.Protected()
            .Setup<Task<HttpResponseMessage>>(
                "SendAsync",
                ItExpr.Is<HttpRequestMessage>(x => x.RequestUri.ToString().Contains("api/send")),
                ItExpr.IsAny<CancellationToken>())
            .ReturnsAsync((HttpRequestMessage request, CancellationToken cancellationToken) =>
            {
                // Read the request content
                var requestBody = request.Content != null
                    ? request.Content.ReadAsStringAsync(cancellationToken).Result
                    : null;

                // Create a response that echoes the request body
                var responseContent = requestBody != null
                    ? requestBody
                    : "No request body";


                // Return the response
                return new HttpResponseMessage(HttpStatusCode.OK)
                {
                    Content = new StringContent(responseContent, Encoding.UTF8, "application/json")
                };
            });

        return mockHandler.Object;
    }

当你看到这个设置 Mock<HttpMessageHandler> 然后,我进入 UmamiClient. 在这个代码中,我把这个插进我们的 IServiceCollection 设置方法@. 这将添加所有需要的服务 UmamiClient 包括我们新的 HttpMessageHandler 然后返回 IServiceCollection 用于测试的“.”

    public static IServiceCollection SetupServiceCollection(string webSiteId = Consts.WebSiteId,
        string umamiPath = Consts.UmamiPath, HttpMessageHandler? handler = null)
    {
        var services = new ServiceCollection();
        var umamiClientSettings = new UmamiClientSettings
        {
            WebsiteId = webSiteId,
            UmamiPath = umamiPath
        };
        services.AddSingleton(umamiClientSettings);
        services.AddScoped<PayloadService>();
        services.AddLogging(x => x.AddConsole());
        // Mocking HttpMessageHandler with Moq
        var mockHandler = handler ?? EchoMockHandler.Create();
        services.AddHttpClient<UmamiClient>((serviceProvider, client) =>
        {
            var umamiSettings = serviceProvider.GetRequiredService<UmamiClientSettings>();
            client.BaseAddress = new Uri(umamiSettings.UmamiPath);
        }).ConfigurePrimaryHttpMessageHandler(() => mockHandler);
        return services;
    }

将它注入到 UmamiClient 然后,我使用这些服务 在 UmamiClient 设置@. @% 1

    public static UmamiClient GetUmamiClient(IServiceCollection? serviceCollection = null,
        HttpContextAccessor? contextAccessor = null)
    {
        serviceCollection ??= SetupServiceCollection();
        SetupUmamiClient(serviceCollection, contextAccessor);
        if (serviceCollection == null) throw new NullReferenceException(nameof(serviceCollection));
        var serviceProvider = serviceCollection.BuildServiceProvider();
        return serviceProvider.GetRequiredService<UmamiClient>();
    }

您将看到我这里有一堆备选参数, 允许我为不同的测试类型输入不同选项@. @%

测试

所以现在我把所有这些设置都安排好了 我现在可以开始为 UmamiClient .

发送

这些设置意味着 我们的测试其实很简单

public class UmamiClient_SendTests
{
    [Fact]
    public async Task Send_Wrong_Type()
    {
        var umamiClient = SetupExtensions.GetUmamiClient();
        await Assert.ThrowsAsync<ArgumentException>(async () => await umamiClient.Send(type: "boop"));
    }

    [Fact]
    public async Task Send_Empty_Success()
    {
        var umamiClient = SetupExtensions.GetUmamiClient();
        var response = await umamiClient.Send();
        Assert.Equal(HttpStatusCode.OK, response.StatusCode);
    }
}

这里您可以看到最简单的测试案例@ , @ 只是确保 UmamiClient 关键是我们也可以测试一个例外案例。 type 这是测试中经常被忽略的部分... ... ,...

页面视图视图

为了测试我们的页面浏览方法 我们可以做类似的东西 在下面的代码里,我用我的 EchoHttpHandler 来回想一下所发送的回复,并确保它将我期待的东西寄回来。

    [Fact]
    public async Task TrackPageView_WithNoUrl()
    {
        var defaultUrl = "/testpath";
        var contextAccessor = SetupExtensions.SetupHttpContextAccessor(path: "/testpath");
        var umamiClient = SetupExtensions.GetUmamiClient(contextAccessor: contextAccessor);
        var response = await umamiClient.TrackPageView();

        var content = await response.Content.ReadFromJsonAsync<EchoedRequest>();
        Assert.NotNull(response);
        Assert.NotNull(content);
        Assert.Equal(content.Payload.Url, defaultUrl);
        Assert.Equal(HttpStatusCode.OK, response.StatusCode);
    }

HtpConcontext 获取器

此处使用 HttpContextAccessor 将路径设置为 /testpath 然后检查 UmamiClient 正确发送@ . @

    public static HttpContextAccessor SetupHttpContextAccessor(string host = Consts.Host,
        string path = Consts.Path, string ip = Consts.Ip, string userAgent = Consts.UserAgent,
        string referer = Consts.Referer)
    {
        HttpContext httpContext = new DefaultHttpContext();
        httpContext.Request.Host = new HostString(host);
        httpContext.Request.Path = new PathString(path);
        httpContext.Connection.RemoteIpAddress = IPAddress.Parse(ip);
        httpContext.Request.Headers.UserAgent = userAgent;
        httpContext.Request.Headers.Referer = referer;

        var context = new HttpContextAccessor { HttpContext = httpContext };
        return context;
    }

这对于我们的Umami客户代码很重要,因为从每项请求中发送的数据大多实际上是动态生成的。 HttpContext 对象@. @}所以我们完全不能发送任何文件 await umamiClient.TrackPageView(); 并且它仍然会通过从电源中提取Url来发送正确的数据 HttpContext.

当我们稍后看到它的时候 ' UserAgent 和 IPAddress 当Umami 服务器在不使用 cookie@.}情况下跟踪数据时,

为了有这个可以预测的,我们定义 一群Consts在 Consts @.#所以我们可以根据可预测的回应和请求来测试_.}

public class Consts
{
    public const string UmamiPath = "https://example.com";
    public const string WebSiteId = "B41A9964-FD33-4108-B6EC-9A6B68150763";
    public const string Host = "example.com";
    public const string Path = "/example";
    public const string Ip = "127.0.0.1";
    public const string UserAgent = "Test User Agent";
    public const string Referer = "Test Referer";
    public const string DefaultUrl = "/testpath";
    public const string DefaultTitle = "Example Page";
    public const string DefaultName = "RSS";
    public const string DefaultType = "event";

    public const string Email = "[email protected]";

    public const string UserId = "11224456";
    
    public const string UserName = "Test User";
    
    public const string SessionId = "B41A9964-FD33-4108-B6EC-9A6B68150763";
}

进一步测试

这仅仅是我们测试Ummi. Net,战略的开始, IHostedService 并对照实际数据测试 Umami 生成了 @(}这是'}记录在任何地方,但含有 JWT 标记和一些有用的数据@.)}*

{
  "alg": "HS256",
  "typ": "JWT"
}{
  "id": "b9836672-feee-55c5-985a-a5a23d4a23ad",
  "websiteId": "32c2aa31-b1ac-44c0-b8f3-ff1f50403bee",
  "hostname": "example.com",
  "browser": "chrome",
  "os": "Windows 10",
  "device": "desktop",
  "screen": "1920x1080",
  "language": "en-US",
  "country": "GB",
  "subdivision1": null,
  "subdivision2": null,
  "city": null,
  "createdAt": "2024-09-01T09:26:14.418Z",
  "visitId": "e7a6542f-671a-5573-ab32-45244474da47",
  "iat": 1725182817
}2|Y*: �(N%-ޘ^1>@V

因此,我们将想要测试是否要模拟此符号并可能返回每次访问的数据 : @(@as you'}当您回忆这是来自 uuid(websiteId,ipaddress, useragent)).

在结论中的结论

这仅仅是测试Umami. @Net profession@,}这里还有很多事情要做 但是这是一个良好的开始

Finding related posts...
logo

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