Names, structure and code you can come back to
Names
A name says what the thing does in the domain's language, not how it's implemented. A name that needs a comment to be understood is a bad name.
Be consistent: the same term for the same concept across the system, including in the database and the interface. Two names for one thing are a constant source of bugs.
Structure
Organize by business domain and not by file type. An “orders” folder holding everything related to orders is easier to navigate than separate folders per layer.
Keep boundaries: a module reaches another through a defined interface, not through internals. Boundaries kept inside one system are what let you split it later if needed.
Simplicity
Prefer boring code. An abstraction created before there were three real cases is almost always wrong, and harder to remove than to add.
Going deeper
When code is hard to test, it's almost always a sign of a dependency tangled with logic. Instead of adding mocks, inject the dependency — the test simplifies and the structure improves together, and that's one of the most reliable signs of a design that needs fixing.