John,
You are asking a question on a topic that is very near and dear to my heart. I also have to concur with Winston's comments about testing being undervalued. Everyone in IT is underpaid, so I will not make a distinction for testers there ;)
I'll assume you are using JUnit as your test framework. So I'll suggest you follow the approach which I have been following for at least two years. It is more or less adapted from Test Driven Development and Agile concepts.
Use the Junit class(es) to document your requirements. If you have a requirements document, then refer to it and reference it in the JUnit javadocs. If you do not have a requirements document, then I suggest using the JUnit javadocs as your requirements. If you are fortunate to have a team that can think out of the box, then using the JUnit javadocs as a requirements
doc eliminates maintenance of a formal requirements doc which can help eliminate some overhead.
Minimally, there should be one test method per requirement. If you want to keep tests very concise, then break the tests up according to the various paths implied by the requirement. Be very descriptive in the method javadoc to state the purpose of the test, the inputs/data values to use, and the expected results. Code the test with a "fail" statement with verbiage like "not implemented" such that you can execute the tests and get an accurate feel for development progress by looking at the pass/value ratio and quickly see which failures are potentially due to tests not being written vs. the application not being written (or not working).
Another aspect to consider is that the requirements based approach will be looking at the application more from a user point of view. If you are writing a component based solution, then the tests should definitely work to validate that the integrated components accurately solve the problem/requirements.
If you are writing components, then the above still applies, but you need to write requirements for the behavior of the component and apply the same approach. At some point you will morph from writing requiements from a "user view" and write them from a more technical view in that your component may do more than required for the immediate project.
You can continue breaking this solution down to a class level for what I'll call "unit" tests for a class. I generally have broken the formal documentation at this point. While the unit tests are part of an automated solution, I look at the requirements based tests essentially as the set of acceptance tests that the code works as needed.
Organize your JUnit classes as you see appropriate. For initial review, having few classes may be appropriate. As you schedule the work and determine release strategies then you will likely want to break the tests up into classes and/or packages organized by release so you can have easier visibility on the progress for a release. For tests "far" in the future, no one needs to be concerned if they fail but you do have a parking lot or todo list as a by product which allows developers with free time to work ahead.
I think you also touched on a point earlier which is that the application/components need to be organized in a way to facilitate testing. I think this is true to some extent, but if you approach the solution architecture using an object-oriented approach and have provisions for swapping the implementation through configuration then you have some natural points to plug in different options to allow for earier testing (API test stubs, default data, etc).
I am glossing over some points of the process such as needing to have your build processes set up to execute everything. At the risk of stating the obvious, here too you have a lot of flexibility in your approach. You can go for an end to end automated solution that provides scripting for the pulling of the code base from version control, building the app, deploying the app, running the tests, and providing a "versioned" set of results so you can look at the build history and see when a certain test "broke", etc. You could also be a simple as just executing things manually when you need them run.
I'll stop the diatribe at the moment. Hopefully this helps give some ideas you can consider adopting for your situation. If there are some aspects that you would like to explore further, just shout.