“You need to write unit tests” they said. But not always it’s specified why do we need to write it. We can have many reasons to create a test for a method, since one can have many different outcomes. That’s why it is important to be capable of precisely defining assertions in unit tests.
What do you mean by “assertion”?
If you are familiar with the AAA pattern, the assertion is the last phase of our unit testing. It’s after arranging our test and acting, we verify if we got the expected result. We can assert multiple conditions, but we should try to keep it as minimum as possible, otherwise we might end up testing multiple conditions on a single test.
Finding out what needs to be tested
You might be wondering about the meaning of a test having multiple outcomes. Fear not, let me show you a piece of code that illustrates it:
public void Drive()
{
if (GasLeft < 0)
throw new OutOfGasException();
if (IsRaining)
throw new OutOfRoofException();
if (LateToWork)
{
// Oh noes the engine is lazy
Thread.Sleep(TimeSpan.FromSeconds(30));
}
IsDriving = true;
}
So, in our “Drive” method, there are 4 scenarios that we need to cover:
- When we’re out of gas
- When it is raining,
- When we’re late to work
- None of the above (the glorious happy case)
After that’s settled, we need to identify what truly defines that we are handling those scenarios. For example, in the first scenario, could we assert by checking if IsDriving is false? While it wouldn’t be wrong, it’s not precisely what we want. If we end up accidentally removing the GasLeft < 0 check, but in our assertion we somehow set our IsRaining property to true, our test would still pass. That means that we risk having a false positive in our test coverage.
If we take a closer look, we can see that if we have no gas, our method will throw an OutOfGasException. That’s what we need to verify, that’s what we do to handle that scenario. In NUnit, our assertion would look something like this:
Assert.Throws<OutOfGasException>(() => car.Drive());
Conclusion
When defining assertions in unit tests, always try to be as precise as possible. You could be tempted to use a generic result as your assertion, but that can lead to false positives in the future. Also, remember to always name your unit tests correctly, so they match what you are testing.