Unit Testing - Effective Tips With bUnit Testing Continued (Part 5)

Posted by Hon Lee on February 06, 2025
    [Fact]
    public void Documents_ShouldReturnValidDocuments()
    {
        // Arrange
        var chatComponent = new Chat();
        var messages = new List<Message>
        {
            new Message
            {
                ConversationId = Guid.NewGuid(),
                Content = new ChatMessageContent
                {
                    Role = AuthorRole.Tool,
                    Content = JsonSerializer.Serialize(new List<DocumentIndex>
                    {
                        new DocumentIndex
                        {
                            Id = "1",
                            DocumentId = "doc1",
                            DocumentName = "Document 1",
                            DocumentLastModified = DateTimeOffset.UtcNow,
                            Content = "Content of document 1",
                            ReRankerScore = 0.9f
                        }
                    })
                },
                UserId = Guid.NewGuid(),
                SentAt = DateTimeOffset.UtcNow
            },
            new Message
            {
                ConversationId = Guid.NewGuid(),
                Content = new ChatMessageContent
                {
                    Role = AuthorRole.User,
                    Content = "User message"
                },
                UserId = Guid.NewGuid(),
                SentAt = DateTimeOffset.UtcNow
            }
        };
        chatComponent.GetType().GetField("messages", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(chatComponent, messages);

        // Act
        var documentItems= chatComponent.GetType().GetProperty("Documents", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(chatComponent) as IEnumerable<DocumentIndex>;

        // Assert
        Assert.Single(documentItems);
        var documentItem = documentItems.First();
        Assert.Equal("1", documentItem.Id);
        Assert.Equal("doc1", documentItem.DocumentId);
        Assert.Equal("Document 1", documentItem.DocumentName);
        Assert.Equal("Content of document 1", documentItem.Content);
        Assert.Equal(0.9f, documentItem.ReRankerScore);
    }

    [Fact]
    public void Documents_ShouldHandleInvalidDocuments()
    {
        // Arrange
        var chatComponent = new Chat();
        var messages = new List<Message>
        {
            new UI.Data.Message
            {
                ConversationId = Guid.NewGuid(),
                Content = new ChatMessageContent
                {
                    Role = AuthorRole.Tool,
                    Content = JsonSerializer.Serialize(new object())
                },
                UserId = Guid.NewGuid(),
                SentAt = DateTimeOffset.UtcNow
            },
            new Message
            {
                ConversationId = Guid.NewGuid(),
                Content = new ChatMessageContent
                {
                    Role = AuthorRole.User,
                    Content = "User message"
                },
                UserId = Guid.NewGuid(),
                SentAt = DateTimeOffset.UtcNow
            }
        };
        chatComponent.GetType().GetField("messages", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(chatComponent, messages);

        try
        {
            // Act
            var documents = chatComponent.GetType().GetProperty("Documents", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(chatComponent) as IEnumerable<DocumentIndex>;
        }
        catch (JsonException ex)
        { 
            // Assert
            Assert.NotNull(ex);
        }
    }

bUnit Test Code

The last few days I have been extremely busy tied up with a lot of bUnit testing to the point that I have to reach a certain percentage on code coverage so having to go through line by line on the code coverage that is highlighted in red, and to extent no prevail, it is quite tricky to test realms and realms of code with embedded branches that you need to test and then halted with a potential await code statement usually halfway down going to a a very tricky area to test that area of the bUnit test.

A useful snippet of code that I would like to share upon that I mentioned in a previous blog post is testing private methods. With Coverlet Code Coverage (https://github.com/coverlet-coverage/coverlet) running on pipeline this would test every part of the code, something I mentioned throughout the day at my general conversations today.

A useufl way to test private method is to use Reflection that we are starting to utilise proving you can unit test private methods, here is how

// Act

var documents = chatComponent.GetType().GetProperty("Documents", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(chatComponent) as IEnumerable<DocumentIndex>;

If Documents was a private object property in the Razor page, you can use.GetType().GetProperty() to call upon the private method using flags (BindingFlags.NonPublic | BindingFlags.Instance), this is a reflection property, and some of you developers are aware, it is a useful way to invoke the properties within the object type.

This then allowed to do the assertion unit tests following this as seen in the code snippet and can even call upon this assertion

// Assert

Assert.Single(documents);

In the second code block of the code snippet, I also wrote a way to manually invoke a try catch statement in the codeblock for testing. See below

try

{

// Act

var documents= chatComponent.GetType().GetProperty("Documents", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(chatComponent) as IEnumerable<AlexandriaIndex>;

}

catch (JsonException ex)

{

// Assert

Assert.NotNull(ex);

}

This is a way to ensure you can do an assert over when an exception, in this case a JsonException is thrown within the code. I will discuss another way you can do this generally using the Assert.Throws in a later blog post.

Hope that helps!