برچسب: check

  • 3 ways to check the object passed to mocks with Moq in C# | Code4IT

    3 ways to check the object passed to mocks with Moq in C# | Code4IT


    In unit tests, sometimes you need to perform deep checks on the object passed to the mocked service. We will learn 3 ways to do that with Moq and C#

    Table of Contents

    Just a second! 🫷
    If you are here, it means that you are a software developer.
    So, you know that storage, networking, and domain management have a cost .

    If you want to support this blog, please ensure that you have disabled the adblocker for this site.
    I configured Google AdSense to show as few ADS as possible – I don’t want to bother you with lots of ads, but I still need to add some to pay for the resources for my site.

    Thank you for your understanding.
    Davide

    When writing unit tests, you can use Mocks to simulate the usage of class dependencies.

    Even though some developers are harshly against the usage of mocks, they can be useful, especially when the mocked operation does not return any value, but still, you want to check that you’ve called a specific method with the correct values.

    In this article, we will learn 3 ways to check the values passed to the mocks when using Moq in our C# Unit Tests.

    To better explain those 3 ways, I created this method:

    public void UpdateUser(User user, Preference preference)
    {
        var userDto = new UserDto
        {
            Id = user.id,
            UserName = user.username,
            LikesBeer = preference.likesBeer,
            LikesCoke = preference.likesCoke,
            LikesPizza = preference.likesPizza,
        };
    
        _userRepository.Update(userDto);
    }
    

    UpdateUser simply accepts two objects, user and preference, combines them into a single UserDto object, and then calls the Update method of _userRepository, which is an interface injected in the class constructor.

    As you can see, we are not interested in the return value from _userRepository.Update. Rather, we are interested in checking that we are calling it with the right values.

    We can do it in 3 ways.

    Verify each property with It.Is

    The simplest, most common way is by using It.Is<T> within the Verify method.

    [Test]
    public void VerifyEachProperty()
    {
        // Arrange
        var user = new User(1, "Davide");
        var preferences = new Preference(true, true, false);
    
        UserDto expected = new UserDto
        {
            Id = 1,
            UserName = "Davide",
            LikesBeer = true,
            LikesCoke = false,
            LikesPizza = true,
        };
    
        //Act
    
        userUpdater.UpdateUser(user, preferences);
    
        //Assert
        userRepo.Verify(_ => _.Update(It.Is<UserDto>(u =>
            u.Id == expected.Id
            && u.UserName == expected.UserName
            && u.LikesPizza == expected.LikesPizza
            && u.LikesBeer == expected.LikesBeer
            && u.LikesCoke == expected.LikesCoke
        )));
    }
    

    In the example above, we used It.Is<UserDto> to check the exact item that was passed to the Update method of userRepo.

    Notice that it accepts a parameter. That parameter is of type Func<UserDto, bool>, and you can use it to define when your expectations are met.

    In this particular case, we’ve checked each and every property within that function:

    u =>
        u.Id == expected.Id
        && u.UserName == expected.UserName
        && u.LikesPizza == expected.LikesPizza
        && u.LikesBeer == expected.LikesBeer
        && u.LikesCoke == expected.LikesCoke
    

    This approach works well when you have to perform checks on only a few fields. But the more fields you add, the longer and messier that code becomes.

    Also, a problem with this approach is that if it fails, it becomes hard to understand which is the cause of the failure, because there is no indication of the specific field that did not match the expectations.

    Here’s an example of an error message:

    Expected invocation on the mock at least once, but was never performed: _ => _.Update(It.Is<UserDto>(u => (((u.Id == 1 && u.UserName == "Davidde") && u.LikesPizza == True) && u.LikesBeer == True) && u.LikesCoke == False))
    
    Performed invocations:
    
    Mock<IUserRepository:1> (_):
        IUserRepository.Update(UserDto { UserName = Davide, Id = 1, LikesPizza = True, LikesCoke = False, LikesBeer = True })
    

    Can you spot the error? And what if you were checking 15 fields instead of 5?

    Verify with external function

    Another approach is by externalizing the function.

    [Test]
    public void WithExternalFunction()
    {
        //Arrange
        var user = new User(1, "Davide");
        var preferences = new Preference(true, true, false);
    
        UserDto expected = new UserDto
        {
            Id = 1,
            UserName = "Davide",
            LikesBeer = true,
            LikesCoke = false,
            LikesPizza = true,
        };
    
        //Act
        userUpdater.UpdateUser(user, preferences);
    
        //Assert
        userRepo.Verify(_ => _.Update(It.Is<UserDto>(u => AreEqual(u, expected))));
    }
    
    private bool AreEqual(UserDto u, UserDto expected)
    {
        Assert.AreEqual(expected.UserName, u.UserName);
        Assert.AreEqual(expected.Id, u.Id);
        Assert.AreEqual(expected.LikesBeer, u.LikesBeer);
        Assert.AreEqual(expected.LikesCoke, u.LikesCoke);
        Assert.AreEqual(expected.LikesPizza, u.LikesPizza);
    
        return true;
    }
    

    Here, we are passing an external function to the It.Is<T> method.

    This approach allows us to define more explicit and comprehensive checks.

    The good parts of it are that you will gain more control over the assertions, and you will also have better error messages in case a test fails:

    Expected string length 6 but was 7. Strings differ at index 5.
    Expected: "Davide"
    But was:  "Davidde"
    

    The bad part is that you will stuff your test class with lots of different methods, and the class can easily become hard to maintain. Unluckily, we cannot use local functions.

    On the other hand, having external functions allows us to combine them when we need to do some tests that can be reused across test cases.

    Intercepting the function parameters with Callback

    Lastly, we can use a hidden gem of Moq: Callbacks.

    With Callbacks, you can store in a local variable the reference to the item that was called by the method.

    [Test]
    public void CompareWithCallback()
    {
        // Arrange
    
        var user = new User(1, "Davide");
        var preferences = new Preference(true, true, false);
    
        UserDto actual = null;
        userRepo.Setup(_ => _.Update(It.IsAny<UserDto>()))
            .Callback(new InvocationAction(i => actual = (UserDto)i.Arguments[0]));
    
        UserDto expected = new UserDto
        {
            Id = 1,
            UserName = "Davide",
            LikesBeer = true,
            LikesCoke = false,
            LikesPizza = true,
        };
    
        //Act
        userUpdater.UpdateUser(user, preferences);
    
        //Assert
        Assert.IsTrue(AreEqual(expected, actual));
    }
    

    In this way, you can use it locally and run assertions directly to that object without relying on the Verify method.

    Or, if you use records, you can use the auto-equality checks to simplify the Verify method as I did in the previous example.

    Wrapping up

    In this article, we’ve explored 3 ways to perform checks on the objects passed to dependencies mocked with Moq.

    Each way has its pros and cons, and it’s up to you to choose the approach that fits you the best.

    I personally prefer the second and third approaches, as they allow me to perform better checks on the passed values.

    What about you?

    For now, happy coding!

    🐧



    Source link

  • 2 ways to check communication with MongoDB &vert; Code4IT

    2 ways to check communication with MongoDB | Code4IT


    Health Checks are fundamental to keep track of the health of a system. How can we check if MongoDB is healthy?

    Table of Contents

    Just a second! 🫷
    If you are here, it means that you are a software developer.
    So, you know that storage, networking, and domain management have a cost .

    If you want to support this blog, please ensure that you have disabled the adblocker for this site.
    I configured Google AdSense to show as few ADS as possible – I don’t want to bother you with lots of ads, but I still need to add some to pay for the resources for my site.

    Thank you for your understanding.
    Davide

    In any complex system, you have to deal with external dependencies.

    More often than not, if one of the external systems (a database, another API, or an authentication provider) is down, the whole system might be affected.

    In this article, we’re going to learn what Health Checks are, how to create custom ones, and how to check whether a MongoDB instance can be reached or not.

    What are Health Checks?

    A Health Check is a special type of HTTP endpoint that allows you to understand the status of the system – well, it’s a check on the health of the whole system, including external dependencies.

    You can use it to understand whether the application itself and all of its dependencies are healthy and responding in a reasonable amount of time.

    Those endpoints are also useful for humans, but are even more useful for tools that monitor the application and can automatically fix some issues if occurring – for example, they can restart the application if it’s in a degraded status.

    How to add Health Checks in dotNET

    Lucky for us, .NET already comes with Health Check capabilities, so we can just follow the existing standard without reinventing the wheel.

    For the sake of this article, I created a simple .NET API application.

    Head to the Program class – or, in general, wherever you configure the application – and add this line:

    builder.Services.AddHealthChecks();
    

    and then, after var app = builder.Build();, you must add the following line to have the health checks displayed under the /healtz path.

    app.MapHealthChecks("/healthz");
    

    To sum up, the minimal structure should be:

    var builder = WebApplication.CreateBuilder(args);
    
    builder.Services.AddControllers();
    
    builder.Services.AddHealthChecks();
    
    var app = builder.Build();
    
    app.MapHealthChecks("/healthz");
    
    app.MapControllers();
    
    app.Run();
    

    So that, if you run the application and navigate to /healthz, you’ll just see an almost empty page with two characteristics:

    • the status code is 200;
    • the only printed result is Healthy

    Clearly, that’s not enough for us.

    How to create a custom Health Check class in .NET

    Every project has its own dependencies and requirements. We should be able to build custom Health Checks and add them to our endpoint.

    It’s just a matter of creating a new class that implements IHealthCheck, an interface that lives under the Microsoft.Extensions.Diagnostics.HealthChecks namespace.

    Then, you have to implement the method that tells us whether the system under test is healthy or degraded:

    Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default);
    

    The method returns an HealthCheckResult, which is a struct that can have those values:

    • Healthy: everything is OK;
    • Degraded: the application is running, but it’s taking too long to respond;
    • Unhealthy: the application is offline, or an error occurred while performing the check.

    So, for example, we build a custom Health Check class such as:

    public class MyCustomHealthCheck : IHealthCheck
    {
        private readonly IExternalDependency _dependency;
    
        public MyCustomHealthCheck(IExternalDependency dependency)
        {
            _dependency = dependency;
        }
    
        public Task<HealthCheckResult> CheckHealthAsync(
            HealthCheckContext context, CancellationToken cancellationToken = default)
        {
            var isHealthy = _dependency.IsHealthy();
    
            if (isHealthy)
            {
                return Task.FromResult(HealthCheckResult.Healthy());
            }
            return Task.FromResult(HealthCheckResult.Unhealthy());
        }
    }
    

    And, finally, add it to the Startup class:

    builder.Services.AddHealthChecks()
        .AddCheck<MyCustomHealthCheck>("A custom name");
    

    Now, you can create a stub class that implements IExternalDependency to toy with the different result types. In fact, if we create and inject a stub class like this:

    public class StubExternalDependency : IExternalDependency
    {
        public bool IsHealthy() => false;
    }
    

    and we run the application, we can see that the final result of the application is Unhealthy.

    A question for you: why should we specify a name to health checks, such as “A custom name”? Drop a comment below 📩

    Adding a custom Health Check Provider for MongoDB

    Now we can create a custom Health Check for MongoDB.

    Of course, we will need to use a library to access Mongo: so simply install via NuGet the package MongoDB.Driver – we’ve already used this library in a previous article.

    Then, you can create a class like this:

    public class MongoCustomHealthCheck : IHealthCheck
    {
        private readonly IConfiguration _configurations;
        private readonly ILogger<MongoCustomHealthCheck> _logger;
    
        public MongoCustomHealthCheck(IConfiguration configurations, ILogger<MongoCustomHealthCheck> logger)
        {
            _configurations = configurations;
            _logger = logger;
        }
    
        public async Task<HealthCheckResult> CheckHealthAsync(
            HealthCheckContext context, CancellationToken cancellationToken = default)
        {
            try
            {
                await MongoCheck();
                return HealthCheckResult.Healthy();
            }
            catch (Exception ex)
            {
                return HealthCheckResult.Unhealthy();
            }
        }
    
        private async Task IsMongoHealthy()
        {
            string connectionString = _configurations.GetConnectionString("MongoDB");
            MongoUrl url = new MongoUrl(connectionString);
    
            IMongoDatabase dbInstance = new MongoClient(url)
                .GetDatabase(url.DatabaseName)
                .WithReadPreference(new ReadPreference(ReadPreferenceMode.Secondary));
    
            _ = await dbInstance.RunCommandAsync<BsonDocument>(new BsonDocument { { "ping", 1 } });
        }
    }
    

    As you can see, it’s nothing more than a generic class with some services injected into the constructor.

    The key part is the IsMongoHealthy method: it’s here that we access the DB instance. Let’s have a closer look at it.

    How to Ping a MongoDB instance

    Here’s again the IsMongoHealthy method.

    string connectionString = _configurations.GetConnectionString("MongoDB");
    MongoUrl url = new MongoUrl(connectionString);
    
    IMongoDatabase dbInstance = new MongoClient(url)
        .GetDatabase(url.DatabaseName)
        .WithReadPreference(new ReadPreference(ReadPreferenceMode.Secondary));
    
    _ = await dbInstance.RunCommandAsync<BsonDocument>(new BsonDocument { { "ping", 1 } });
    

    Clearly, we create a reference to a specific DB instance: new MongoClient(url).GetDatabase(url.DatabaseName). Notice that we’re requiring access to the Secondary node, to avoid performing operations on the Primary node.

    Then, we send the PING command: dbInstance.RunCommandAsync<BsonDocument>(new BsonDocument { { "ping", 1 } }).

    Now what? The PING command either returns an object like this:

    or, if the command cannot be executed, it throws a System.TimeoutException.

    MongoDB Health Checks with AspNetCore.Diagnostics.HealthChecks

    If we don’t want to write such things on our own, we can rely on pre-existing libraries.

    AspNetCore.Diagnostics.HealthChecks is a library you can find on GitHub that automatically handles several types of Health Checks for .NET applications.

    Note that this library is NOT maintained or supported by Microsoft – but it’s featured in the official .NET documentation.

    This library exposes several NuGet packages for tens of different dependencies you might want to consider in your Health Checks. For example, we have Azure.IoTHub, CosmosDb, Elasticsearch, Gremlin, SendGrid, and many more.

    Obviously, we’re gonna use the one for MongoDB. It’s quite easy.

    First, you have to install the AspNetCore.HealthChecks.MongoDb NuGet package.

    NuGet package for AspNetCore.HealthChecks.MongoDb

    Then, you have to just add a line of code to the initial setup:

    builder.Services.AddHealthChecks()
        .AddMongoDb(mongodbConnectionString: builder.Configuration.GetConnectionString("MongoDB"))
    

    That’s it! Neat and easy! 😎

    Why do we even want a custom provider?

    Ok, if we can just add a line of code instead of creating a brand-new class, why should we bother creating the whole custom class?

    There are some reasons to create a custom provider:

    1. You want more control over the DB access: for example, you want to ping only Secondary nodes, as we did before;
    2. You don’t just want to check if the DB is up, but also the performance of doing some specific operations, such as retrieving all the documents from a specified collection.

    But, yes, in general, you can simply use the NuGet package we used in the previous section, and you’re good to go.

    Further readings

    As usual, the best way to learn more about a topic is by reading the official documentation:

    🔗 Health checks in ASP.NET Core | Microsoft Docs

    How can you use MongoDB locally? Well, easy: with Docker!

    🔗 First steps with Docker: download and run MongoDB locally | Code4IT

    As we saw, we can perform PING operation on a MongoDB instance.

    🔗 Ping command | MongoDB

    This article first appeared on Code4IT 🐧

    Finally, here’s the link to the GitHub repo with the list of Health Checks:

    🔗 AspNetCore.Diagnostics.HealthChecks | GitHub

    and, if you want to sneak peek at the MongoDB implementation, you can read the code here:

    🔗 MongoDbHealthCheck.cs | GitHub

    Wrapping up

    In this article, we’ve learned two ways to implement Health Checks for a MongoDB connection.

    You can either use a pre-existing NuGet package, or you can write a custom one on your own. It all depends on your use cases.

    I hope you enjoyed this article! Let’s keep in touch on Twitter or LinkedIn, if you want! 🤜🤛

    Happy coding!

    🐧





    Source link