Unit tests can be formatted and structured in a wide variety of ways.
At Campus, we have been structuring our unit tests in a similar manner in order to promote consistency in our code and to make it easier to create new tests. By simply following the basic structure explained below, you can create unit tests that will be consistent with other Campus solutions.
Below is a sample unit test class structure. Below the example, there is an explanation of each section in the structure of this test class.
public class [NameOfClassBeingTested]Tests
private Mock _mockDependantClass = new Mock();
private ClassBeingTested _sut;
public void Init()
_sut = new ClassBeingTested(_mockDependantClass.Object);
public void [MethodBeingTested]_[ConditionBeingTested]_[ExpectedResults]()
_mockDependantClass.Setup(x => x.SomeMethod(It.IsAny())).Returns("SomeExpectedValue");
var input = new Student();
var result = _sut.MethodBeingTested(input);
Line 1-2. Use the name of the class being tested and add the word “Tests” at the end.
Line 5. Declare (as private properties) and instantiate all dependent classes that you will need to mock in order to be able to test a class in isolation from all other classes.
- Name all properties that are going to be mocked as follows:
“_mock[Name of Class Being Mocked]”.
i.e. _mockStudentServices, or _mockRegistrationServices.
- If you need to create more than 3 mock dependent classes, try to declare them in alphabetical order. This will make it easy to detect any mistaken duplicates.
Line 6. Declare (as a property) the class you want to test in isolation.
- Name this property “_sut”.
(This means “System Under Test” or SUT.)
- Declare it last so that it is easy to tell what is being tested
Line 8-13. Create a method named Init() where you will create the instance of your sut class.
- In this method, you can pass to the _sut any dependencies that you have mocked using constructor injection or property injection.
- You can use this method for any setup steps that are common for all of your tests
Line 16. Please remember to identify each unit test by adding a [TestCategory(“UnitTest”)] attribute.
- This is a very important point. By identifying a unit test with this category we can make configure Visual Studio to run the tests on every build. We can also tell Visual Studio to ignore any other test marked as [TestCategory(“IntegrationTest”)]
Line 17. Name your unit test using the following format:
[Name Of Method Being Tested] + “_” + [Description of scenario being tested] + “_” + [Description of expected result]
Line 19. Perform any setup steps you need to arrange on your mocked classes.
- These steps will vary based on the scenario you are trying to test.
Line 20. Define the input that you will be providing to the method being tested.
- Try to name any variables/classes that will be used as input so that it is easily understood their purpose.
- Name input values to describe the values in each variable or class being used as input.
i.e. anyString, anyDate, anyStudent, studentWithMissingCourses, etc.
Line 23. Execute the method being tested
- On most unit tests, you should only have method being executed in the SUT class.
- The default name for the value returned from the method being tested should be “result”
- (Code smell!) If you need to execute multiple methods on the SUT in order to perform a single unit test then you may need to examine the class or method being tested. This is an indication that the class being tested may need some decoupling or refactoring.
Line 26. If you perform any setup steps for your mocked classes, you should use ValidateAll() to make sure that those steps got executed during the execution of the test.
Line 27. Perform assertions to determine if the “result” output matches your test expectations.
* You can add multiple ASSERT statements at the end of each test.