This is a spectacularly thoughtful and insightful piece by Eugen Kiss on testing:
Different kinds of tests have different costs and benefits. You have finite resources to distribute into testing. You want to get the most out of your tests, so use the most economic testing approach.
He goes on to describe why he believes that integration tests provide better ROI than unit tests and end-to-end tests. Then he turns his aim on unit tests in particular:
There is the claim that making your code unit-testable will improve its quality. Many arguments and some empirical evidence in favor of that claim exist so I will put light on the other side… Unit tests ossify the internal structure of the code.
Click through to read his whole argument, but I will say in my experience unit tests only ossify the structure when I do them poorly. In other words, the better I get at unit testing, the more useful they become. In light of that, Eugen’s big takeaway at the end might be 💯 on point:
If you desire clear, albeit unnuanced, instructions, here is what you should do: Use a typed language. Focus on integration and end-to-end tests. Use unit tests only where they make sense (e.g. pure algorithmic code with complex corner cases). Be economic. Be lean.