An issue that comes up frequently is the relationship between unit testing and the design of the system being tested. So it's probably best that I cover this first.
When you write unit tests, sometimes you feel compelled to change your code just to facilitate the test, usually when you need to test a private method or attribute. Doing so is a bad idea. If you ever feel tempted to make a private method public purely for testing purposes, don't do it. Testing is meant to improve the quality of your code, not decrease it.
Having said that, sometimes designing your system in a way that makes testing easier is still necessary. If you need to add a design element to support testing, ensure that it also increases the general quality of the system as a whole. If the design element doesn't, then you're designing your system only to facilitate testingwhich I must stress again is a bad idea.
For example, you may have a system that connects to a database. It may be advantageous to allow your system to connect to a test database as well as a development database. If you design it in a way that allows the database to be configured then you're facilitating testing, but you're also increasing the quality of the design because the design makes your system more flexible (the first real benefit is that it'll be able to connect to the production database without changing the code!). This design decision benefits both the system and the tests and thus is a good decision.
Say you have a class that can be instantiated only through a factory method (e.g., "Gang of Four"). You may need to test an object of this class, but for some reason you can't call the factory. It may require resources passed as parameters that you don't have in your testing environment. Should you make the default constructor public just so your tests can instantiate the object and run the tests? No, of course not. That would reduce the quality of the system's design, allowing anyone to access a constructor that should be private. In this scenario, the tester needs to work harder to provide the needed resources and instantiate the object through the factory (perhaps through the use of MockObjects).
Now that I've addressed this issue, let's examine some solutions to common testing problems. The first problem is determining how to test non-deterministic code.