UNIT TESTING IS AN IMPORTANT PART OF SOFTWARE DEVELOPMENT WHICH IS OFTEN OVERLOOKED SINCE, AT FIRST GLANCE, IT DOESN’T SEEM TO DIRECTLY IMPACT PROJECT DEVELOPMENT.
Besides the time spent training the development team to write unit tests, there is also the time spent maintaining those which will inevitably break as the codebase evolves. It might seem like a lot of work. So why should we bother?
Unit testing is a type of a software testing method where small components (units) are tested to determine if they behave as expected. These tests should not cross their own unit boundary as this turns them into integration tests - another important testing method, with its own advantages and disadvantages.
There are a number of key benefits to unit testing. As a project grows in size and complexity, it becomes increasingly hard to modify a part of the system without the risk of another part breaking. And while unit testing is not a silver bullet, it provides us with many advantages:
Now that we know what unit testing is and why it’s essential, let's look at how can we apply it on a .NET Framework project. We are going to use xUnit.net as the testing tool, Moq as the mocking framework and Autofixture to generate objects for us.
Let’s say we have a music store where we save information about the album, artist, available stock and format (CD, Vinyl, digital). A store employee can create, delete and modify existing entries in the store. Let’s say we want to test the following method that retrieves the album ID:
In this simple case, we retrieve an entry from the repository and have 2 possible outcomes: either the entry is null or is not null, in which case the entry is returned.
The unit tests we write serve as documentation for the system, so naming and organizing the test projects should follow best practices. Test projects should follow the same folder organization as the tested project and are usually named ProjectName.Tests. Keep in mind that as your project grows you might also want to write integration tests and in which case a better naming scheme would be ProjectName.UnitTests and ProjectName.IntegrationTests.
This particular method is contained in the InventoryService class, so let’s create an InventoryServiceTests class in our newly created test project. This will contain all the tests for the InventoryService class.
When it comes to naming tests, there are multiple approaches, all with their own strengths. I personally use MethodName_StateUnderTest_ExpectedBehavior as it’s pretty descriptive, and makes it easy to find the method being tested.
Now we’re ready to create our first test. Remember that in our case, the method being tested can either return the entity with the given album ID, or throw an exception, if the album ID isn’t valid. So let’s test for both scenarios:
After running the test, it successfully passes. Let’s move on to the next scenario:
Modifications to the class illustrate some important points:
After running our newly created tests we can see that our code coverage is 100%. This isn’t always possible to achieve in the real world due to time constraints. For this reason, you should always give priority to critical paths when implementing unit tests. It’s also important to give unit test to fixed bugs, to prevent regressions.
Unit testing is a learning curve and may take some time to get used to. But combining different tools such as xUnit, Moq and AutoFixture can make creating and maintaining unit tests a breeze.
Cloud has been a topic of introduction and discussion over the years, often perceived as intricate and almost otherworldly—a kind of magic that could came straight out of a tale from C. S. Lewis. However, the reality is far from magical - it is actually quite mundane.
With Learning Technologies 2023 on the horizon, we’ve decided to share some critical components for custom software in enterprise learning. There is a wide range of solutions, but we will focus on 3 essential solutions most applicable to many teams.