Three Pillars of a Unit Test

  • Post published:May 3, 2020

Unit testing is an important phase in any software engineering project and can never be ignored.

This is a level of software testing where individual units of a software system are tested with the purpose of ensuring that each unit of the software performs as it was intended. A unit is the smallest testable part of the software.

There are a number of unit testing frameworks, stubs, mocks and fake objects available to assist with unit testing.

Three pillars of a unit test is a guideline used to layout a single unit test. This guideline divides a single unit test into three parts; namely unit test case, unit test definition and unit test rule. Each part has three steps to address.

Unit test case

  • What are you testing?
  • What are the conditions?
  • What is the expected result?

Unit test definition

  • Arrange
  • Act
  • Assert

Unit test rule

  • Independent
  • Readable
  • Maintainable

Example of applying the three pillars of a unit test using .net core

As an example, create a solution named InternalsDemo with two projects:

  • InternalsDemo – Class Library (.NET Standard)
  • InternalsDemo.Tests – xUnit Test Project (.NET Core)

Install the following nuget packages in the InternalsDemo.Tests project:

  • AutoFixture
  • Moq
  • FluentAssertions

Reference InternalsDemo in the InternalsDemo.Tests project. Also allow the internal members of the InternalsDemo project to be visible in the test project. Refer to this article if you are unsure on how to make internal members visible to other assemblies in .net core.

In the InternalsDemo project, create the following classes.

Create the following class in the InternalsDemo.Tests project.

The above code base created a HeroService, providing a feature to retrieve a list of heroes from a data store. The repository containing the heroes has not been implemented as yet. The focus for now is to ensure that the HeroService is behaving as intended, that is, if heroes exists, then the HeroService will retrieve all the heroes from some sort of data store.

The three pillars of a unit test will be used to create a unit test to test this feature.

The first part is the unit test case.

Unit test case
What are you testing?GetAll
What are the conditions?WhenHeroesExist
What is the expected result?ThenShouldReturnAllHeroes

Using the above table create the following unit test in the HeroServiceTests class.

To implement the unit test, the unit test definition part needs to be addressed.

Unit test definition
ArrangeCreate mock heroes and a mock repository.
ActInvoke the hero service to get all heroes.
AssertCheck that the data received from the service matches what was in the repository.

Using the above table, the unit test can be constructed as follows:

Finally, the last part of the three pillars of a unit test can be addressed.

Unit test rule
IndependentThe unit test is not dependent on any other unit test. It is loosely coupled and can be run at anytime providing the same output.
ReadableThe code is structured neatly and is descriptive. Good naming conventions are used for variables, that is, mock classes include mock in the variable name. Expected heroes and actual heroes are clearly defined.
MaintainableThe unit test is independent, readable and simple since it is only testing a single unit of the software. It can be easily maintained if the GetAll() feature changes.

Summary

The three pillars of a unit test is a powerful guideline to use since it ensures that developers are writing meaningful unit tests that are independent, readable and maintainable. This guideline also applies consistency across any unit test project.

The source code used in this article can be found here.

Software versions used in this article

  • Visual studio 2019 v4.8.03752
  • .net standard v2.0.3
  • AutoFixture v4.11.0
  • Moq v4.14.1
  • xunit v2.4.1
  • FluentAssertions v5.10.3
  • ReSharper Ultimate v2020.1.1