Unit tests are a great way to get quick feedback about your code. They're like an extension of the compiler that's business logic-aware. A comprehensive suite of unit tests can prevent the introduction of stupid bugs, can speed up your release pipeline, and are a boon when you or some other developer has to make a change to code you've written long ago. The maturity and ubiquity of JUnit and supporting tooling have made the barrier to unit test entry extremely low. Heck, you have to explicitly tell Maven not to run unit tests.
With all of these benefits and conveniences, why would a developer not want to write unit tests? Forget TDD, even; I'm talking about not writing unit tests at all.
Here are my theories.
1. You're a Body Shop Developer
Perhaps there is a better term for this, but I believe there is a class of developers who are in the gig solely to earn a paycheck. They're the types that just do what they're told; no more, no less, and usually without any reservations. Management wants to target JavaEE 5. "Sounds good. I know JSP." All developers must use the same IDE: Rational Software Architect. "Sure thing, boss." Our coding standards require Hungarian notation. "No problem." If the developers are not required to write unit tests, they won't do it; neither will they volunteer to write unit tests because that would just be extra work the client would get for free.
2. You Don't Know Any Better
Developers just starting out may be unaware that unit testing is even a thing. (Perhaps IT education has improved since I went to college; all I can say is that I was able to earn a B.S. in Computer Science without knowing anything about unit testing.) This is where a strong, experienced development team lead is important; somebody who can establish the code of conduct for the team with rules like, "If you break the CI build, don't leave the office until it's fixed," "No SNAPSHOT dependencies in the POMs," and "Don't submit a PR without unit tests."
3. You Write Terrible Code
Some developers have no qualms writing low-level JDBC code inside a Servlet. To them, separation of concerns and high cohesion are just highfalutin computer science concepts. My guess is that these kinds of developers rarely write unit tests because their code is essentially untestable. The thought of just mocking up all of the necessary dependencies is daunting enough to make them abandon the idea altogether. Even if you do have some respect for those highfalutin computer science concepts, you may still have coding habits that negatively impact the testability of your code, resulting in a diminished regard for unit testing. Field injection, anyone?
4. You Suffer From Hubris
Admittedly, I find myself fighting against this at times, especially when I'm working solo. I begin to consider my code well-designed and simple enough to make unit tests largely unnecessary. Of course, when I remind myself that I'm a professional and begrudgingly crank some tests out, I inevitably find a bug or discover some important design feedback. The best way to deal with excessive pride, in my opinion, is to work on a team of comparably talented peers and to keep code quality metrics as transparent as possible. It's hard to believe you're a superstar when the CTO's dashboard shows that your project has the lowest code coverage in the company.
5. You're a Cowboy or Consultant
I borrowed this phrasing from John Berryman. Cowboys tend to gain their reputation by quickly solving urgent problems, often at the expense of software development rigor. Consultants, particularly those brought in to establish software architectures at the onset of development efforts, will produce prototype-quality code. There are few tests (if any) because their purpose is to prove out an application architecture rather than to produce fully functioning software. In both cases, unit testing is not perceived to add value to the tasks at hand. Whether or not their perception is correct is debatable, but as someone who has acted in both a cowboy and consultant role, I can attest that the perception is real.
6. Your Spirits Are Crushed
Maybe the code you're working on has no chance of making it to production. Maybe your userbase is just a handful of jerks. Perhaps your company's vision isn't aligned with your own, and every line of code you write is a reminder of other code you could be writing instead. Regardless of the reason, if you're apathetic or resentful to code you're working on, you probably won't care enough to unit test it. Here's an idea: Use the time you should be writing unit tests on looking for a new job.
7. Your Corporate Culture Does Not Value Unit Testing
Project-driven organizations tend to disregard the importance code quality and maintainability because completing projects on time and within budget is the primary focus. Project management doesn't care that much if the project yields well-written code with a comprehensive suite of automated tests. Those are longer-term benefits that won't be realized until well after the project is over and management has shifted attention to other projects.
8. You Inherited a Convoluted Codebase
From my experience, maintenance developers for large, complex, terribly written codebases tend to do little unit testing. Some of this could be attributable to crushed spirits or perhaps because maintenance development teams tend to be staffed with more junior developers or body shop personalities. It could also be attributable to the overall effort vs. value imbalance. Writing unit tests for the codebase would require such extensive refactoring that developers refuse to undertake the task ("Please, just let us rewrite the thing from scratch!"). Similarly, management could be unwilling to invest in work required to expand the unit test suite, money-wise or time-wise. The latter goes back to a project-driven culture's focus on short-term objectives at the expense of investing in longer-term code maintainability. This very same focus is probably what led to the creation of the convoluted code base.
9. Your Corporate Culture Unwittingly Disincentivizes Unit Testing
A company that values unit testing may actually discourage it if its incentive structures are out of alignment with those values. One example could be a project-driven company that superficially enforces unit testing, like by only checking if developers complete their mandatory "Write Unit Tests" task for every user story, but strictly enforces that project deadlines and scope are met. Another example could be a company gives a bonus to the developer who fixes the most bugs that month, regardless of who was responsible for introducing the bugs. This sort of policy encourages some developers to release risky code into production as it creates opportunities to increase their bug fix tally.
These are all potentially valid reasons for not writing unit tests, but they're not necessarily valid excuses. I've been negligent in my unit testing for too long; it's time for me to take it more seriously.