In the domain of strong static typing (not necessarily functional), we might hear phrases like “It compiles, therefore, it must be correct , and thus we don’t need tests!”
While it is true that certain kinds of tests can be omitted in favor of strong static typing, such a stance overlooks that even a correctly-typed program may produce the wrong output.
The other extreme (coming from dynamically-typed land) is to substitute typing with testing, which is even worse. Remember that testing is usually a probabilistic approach and cannot guarantee the absence of bugs. If you have ever refactored a large codebase in both paradigms, you will very likely come to esteem a good type system.
Types of tests
Let us think a bit about the kinds of tests we need.
Our service must read and create data in the JSON format. This format should be fixed and changes to it should raise red flags because any changes would mean that our API just broke.
We want to unleash the power of ScalaCheck to benefit from property-based testing. But even when we’re not using that, we can still use ScalaCheck to generate test data for us.
In addition to the regular unit tests, there should be integration tests if a service is written. We can test a lot of things on the unit test side, but in the end, the integration of all our moving parts is what matters, and often (usually on the not-so-pure side of things) we would have to mock a lot to test things in isolation.