A couple of thoughts...
Yes, I think it does have drawbacks, they may learn from the code, but they may also be steered too much. I guess it depends on what you give them and in how much detail.
Also, unit tests usually focus on a single class. Any unit test would therefore reveal way too much detail of what needs to be taken into consideration when implementing the problem. Which is something they should learn the hard way and not be handed on a silver platter.
For example, consider edge cases: passing an empty string, passing in a value just on the exact limit of the domain, did I need a A > B or an A >= B test, etc. I think everybody needs to fail to allow for an edge case and "suffer" the consequences at least once, preferably more. You simply need that experience to get in the habit of "considering the edges".
Another thing is that unit tests are very specific to the class/function they test. So if your students are to implement these on their own, how can you code your unit tests in advance? For classes you could consider "coding" your tests against an interface declaration (good habit for your students to pick up). For functions you could give them the function declaration (its signature) I guess. In any case you will have to specify some sort of contract for them to stick to with their implementations, or you can't do anything in advance that would allow you to test all your students' work with the same unit tests.
If it is the accuracy of the problem statement you are after. There are other ways. And one that I think would teach them something about how to do an intake of a problem statement (or when they are let loose in the real world: the specification of a feature). I would suggest not giving them the unit tests, but a write up of the "requirements" in simple statements that could be transformed into the function/method names of unit tests.
I have gotten in the habit of naming my unit tests in terms of "A Should B". Where A is a situation to test and B is the desired outcome.
Examples:
procedure YearDigitsShouldRevertToDefaultForLessThanShortYear;
procedure YearDigitsShouldRevertToDefaultForBetweenShortAndLongYear;
procedure YearDigitsShouldRevertToDefaultForMoreThanLongYear;
procedure Custom_VariableSequence_ShouldZeroDigits;
procedure Custom_FixedSequence_ShouldSetDefaultDigitsWhenSpecifiedAsZero;
procedure Custom_FixedSequence_ShouldSetMinimumDigitsWhenSpecifiedBelowMinimum;
procedure Custom_FixedSequence_ShouldSetMaximumDigitsWhenSpecifiedOverMaximum;
Yes, it does make for long names, but it is self-documenting albeit in "short hand". And it allows for a specific test for each specific situation. What's more, most of these can be "generated" from a less accurate narrative description of a problem statement or feature specification.
When faced with a narrative description of an algorithm, nowadays I tend to break it down into single "A should B" statements and verify those with whomever wrote the specs. After which setting up my unit tests is a breeze: I just need to convert the statements into descriptive function names...