for simple scenarios
In your example of
arr_of_sins, it has two dependencies:
Array.new, however, both of these are used statically and thus to be confident in your tests you must treat it as you wrote the
Array.new methods yourself in the class your testing.
This sounds completely ridiculous, but this is the problem of static dependencies that you cannot determine how your logic uses them.
For your particular case,
sin can be safely and easily used in any context, so for your test you could call
sin itself to see if the result of your class matches up with the expected outcome, however, you will soon find that your unit test will look exactly like your production code, which is pointless.
I would follow @Telastyn's answer and do the cases to get a good approximation of the range of outputs you can expect.
for complex scenarios
The problem arises when you get into more complex scenarios where you're testing code which relies on other systems / sub-systems. This is where patterns like dependency injection and mockism can help with making your unit tests robust.
For example, if you're testing some code which relies on getting data from another system, say you need to build a report in CSV format from a query on a database.
If a CSV formatter and a repository are dependencies of your report generator, then you can mock both those dependencies out and all you end up testing is that your class uses the dependencies in a way you expect and not that they go to the database to execute query xyz.
You write unit tests to ensure that the content of the methods your testing are correct, if you assume that
sin behaves as expected that's fine, but you still need to ensure that the unit you're testing is in fact calling
sin, and in the example above, the only way to do that is to verify the output.
This is fine for smaller units where the static dependencies have no dependencies of their own, but for more complex cases you need to have a different strategy to ensure the unit your testing is correct.