How to write code that is hard to test?
– most people say: making things private, using private keyword, long methods (monolythic code)
- mixing “new” operator with business logic prevents you from testing things in isolation (wrong: creating new objects directly in the business logic instead of using them)
- looking for things
- business logic in the constructor (in constructor you should ask for dependencies by constructor arguments and assign them to instance fields. Business logic should be in methods that use these dependecies but not construct them)
- having global state
- using static methods (which is essentialy procedural programming), it is easy to test leaf methods that do not call anybody else (Math.absolute(value)), but if a this static method has a bunch of collaborators then you cannot test this method in isolation, you cannot mock the db (cannot override static method). The worst thing is trying to test your application from the main method.
- deep inheritance hierarchy (if your class under test extends A, B, C classes you are also testing those classes if you want or not)
- too many conditionals (if statements – you need to prepare lots of test data to get throught the path you want)
Scope of tests
- Large number of unit tests – class level tested in insolation – very fast tests
- Many functional tests – collection of classess as subsystem – medium tests
- Some scenario tests – for the whole system – slow tests
The end to end tests are important but they take a lot of time and there are so many things that can go wrong so making sure every is set up correctly is hard and time consuming. It is hard to reproduce failures. Better test smaller portions of program and some happy path (all the things are wired up together correctly). Break the applicaion into subsystem and even invidual components and test the invidually.
For bad code it is hard to write good test.
In order to test classes with dependencies you should be able to have a choice to:
- mock dependencies or
- stub dependencies or
- instantiate a real class that has been alread well tested.