How to Write Simple Unit Tests
Simple Unit Tests
In this article, JUnit will be the testing framework that is used for examples.
Simple unit tests will test only one thing and follow the same three steps in the following order.
Setup
Define the data that the test is going to be using. Some unit tests may not require test data, and this step would be skipped.
Exercise
This is calling the method that is being tested.
Assert
One or more asserts that verify the result of the method being exercised is as expected. If you are mocking in your tests, you may have verifies and asserts in this step.
Using These Steps
An example of using these three steps would be:
public final class UserDaoTest {
@Test
public void returnsUserWhenFoundById() {
// Setup
final User user = create();
// Exercise
final User result = userDao.findById(user.id());
// Assert
assertThat(result.id(), is(user.id());
}
}
Testing Only One Thing
Tests should test only one thing but not be so simple that you complicate the test class with too many little tests. If you had a method that loads a user from the database, there are two outcomes for this method. One is it returns a user, and the other is it throws an exception if the user isn't found. For this, you would want two difference tests.
public final class UserDaoTest {
@Test
public void returnsUserWhenFoundById() {
// Setup
final User user = create();
// Exercise
final User result = userDao.findById(user.id());
// Assert
assertThat(result.id(), is(user.id());
}
@Test
public void throwsExceptionWhenNotFoundById() {
// Setup
final long missingUserId = 0L;
// Exercise the method and assert
assertThrows(
NoResultFoundException.class,
() -> userDao.findById(missingUserId);
);
}
}
Don't Oversimplify
You have an enumeration, and the ordinal value is saved to the database. Changing the ordinal would break existing data and load the wrong enumeration. You would want to have tests that fail if these ordinal values change. You could break each one of these up into individual tests, but a simpler way in this case would be to combine them all in one test.
public enum Color {
GREEN,
YELLOW,
BLUE
}
public final class ColorTest {
@Test
public void ensureOrdinalsNeverChange() {
// Exercise/Assert
assertThat(Color.GREEN.ordinal(), is(0));
assertThat(Color.YELLOW.ordinal(), is(1));
assertThat(Color.BLUE.ordinal(), is(2));
}
}
Conclusion
Keeping tests simple requires each test to test only one thing. Each test should follow the same three steps without repeating them.