When testing code that uses HttpClient, the traditional approach involves mocking HttpMessageHandler using frameworks like Moq. While this works, it can be verbose, ceremony-heavy, and frankly a bit ugly. There's a cleaner alternative: using DelegatingHandler…
Playwright is Microsoft's official solution for modern browser automation, offering multi-browser support (Chrome, Firefox, Safari) with a single API, built-in trace debugging, and mobile emulation. This guide covers everything from setup to advanced testing…
Modern E2E (End-To-End, using your site like users would) testing doesn't have to be painful. This comprehensive guide shows you how to use PuppeteerSharp for fast, reliable browser automation in .NET-covering everything from basic testing to PDF generation…
In the previous part of this series where I tested Umami.Net tracking methods The Problem In the previous part I used Moq to give me a Mock<HttpMessageHandler> and return the handler used in UmamiClient, this is a common pattern when testing code that uses…
I'm a relative noob using Moq (yes I'm aware of the controversies) and I was trying to test a new service I'm adding to Umami.Net, UmamiData. This is a service this allows me to pull data from my Umami instance to use in stuff like sorting posts by popularity…
In the previous article, we discussed how to test the UmamiClient using xUnit and Moq. In this article, we will discuss how to test the UmamiBackgroundSender class. The UmamiBackgroundSender is a bit different to UmamiClient as it uses IHostedService to stay…
Now I have the Umami.Net package out there I of course want to ensure it all works as expected. To do this the best way is to somewhat comprehensively test all the methods and classes. This is where unit testing comes in. Note: This isn't a 'perfect approach'…
In this post I'll be starting adding Unit Testing for this site. This won't be a full tutorial on Unit Testing, but rather a series of posts on how I'm adding Unit Testing to this site. In this post I test some services by mocking DbContext; this is to avoid…