Simple answer: NO.
Complex answer: Maybe
If you have simple and straightforward requirements, how about using JUnit and annotations? This works on the lowest level of the code.
For anything more complicated than a single method, you should use a truth table.
The Source of the Disconnect
Let's back up a bit. One of the measures of what makes a good requirement is that it is testable. This means that theoretically it should be possible to link code, maybe through a JUnit test, to a given requirement. The challenge to be faced, assuming all your requirements are testable, is one of granularity. Requirement gathering has been moving towards use cases or user stories to capture and organize requirements. Most use cases involve describing the steps that must be taken, along with any assumptions involved, to achieve a specified outcome. It is usually pretty simple to turn a requirement into a test case; if the requirement is that the system produce a result of abc when fed xyz, the test is "Input xyz, successful result: abc". When you go to write your JUnit, the process involved may take so many components that to test it requires so much setup and configuration that it takes more time to keep fixing the test than to keep writing application code. Unit tests are meant to test a very narrow range of interactions and to attempt to combine the scenarios results in very fragile and time-consuming tests.
Also, when you consider how code is usually developed as a set of layers to handle similiar responsibilites, User Interface or database for example, they are coded in the general sense and not just for a single use case. If we tried this with the ever popular ATM example, we could use the use case "User logs into system". The variations alone create a large number of paths through the code; types of users, login validation errors, user interface options, and so forth. If we code the database layer, we don't code
getCredentialsForLogin(User u)
it would look more like
getCredentials(User u)
so that it could be used in multiple circumstances, like balance transfers or session timeouts.
Better yet, we would write
getAccountStatus(User u)
not
canUserLogin(User u)
This means that the code in our layers will probably satisfy a large number of requirements. You could try to list them all but that creates an accounting-type headache. If you only listed one requirement you risk not handling a requirement and hoping that your QA group is thorough.
Trying to create JUnit tests in this manner will likely push the framework beyond its design limits.
The Requirement-based Approach
You will be better off investing that time into a more detailed test plan which covers all the important variations with a focus on examples. The most effective I've found is when you setup the entire transaction and any assumptions and provide the expected results. I've found truth tables to be invaluable in quickly creating the complete list of valid scenarios.
You do it by listing the different variables (specified as boolean conditions) being tested together so you can see all the combinations. If our variables were valid user, comm link down, valid PIN, and account locked, we would create a table with 16 columns representing the unique combination of each variable.
Condition / # | 01| 02| 03| 04| 05| 06| 07| 08| 09| 10| 11| 12| 13| 14| 15| 16|
==================================================================================
Valid User | T T T T T T T T F F F F F F F F |
Commlink up | T T T T F F F F T T T T F F F F |
Valid PIN | T T F F T T F F T T F F T T F F |
Account unlocked | T F T F T F T F T F T F T F T F |
================================================================================
Then you list out your 16 distinct scenarios:
01) Valid user, commlink up, valid PIN, account unlocked
02) Valid user, commlink up, valid PIN, account locked
03) Valid user, commlink up, invalid PIN, account unlocked
04) Valid user, commlink up, invalid PIN, account locked
05) Valid user, commlink down, valid PIN, account unlocked
06) Valid user, commlink down, valid PIN, account locked
07) Valid user, commlink down, invalid PIN, account unlocked
08) Valid user, commlink down, invalid PIN, account locked
09) Invalid user, commlink up, valid PIN, account unlocked
10) Invalid user, commlink up, valid PIN, account locked
11) Invalid user, commlink up, invalid PIN, account unlocked
12) Invalid user, commlink up, invalid PIN, account locked
13) Invalid user, commlink down, valid PIN, account unlocked
14) Invalid user, commlink down, valid PIN, account locked
15) Invalid user, commlink down, invalid PIN, account unlocked
16) Invalid user, commlink down, invalid PIN, account locked
Now you have a list of all the possible combinations of those conditions. If any of them are duplicated or impossible because of other business rules, you just document the reason and then they can safely be skipped. For example it might not matter whether the account if locked if the commlink is down. The order of the conditions can be rearranged to facilitate these types of business rule relationships.
Truth tables were the secret behind how we made sure a last-minute, over-the-holidays, huge business opportunity could be implemented in a matter of weeks even though it completely blew major assumptions in almost every module of the existing system.