Direct access to resources has a negative impact on testability. Take the SharePoint log as an example. It is hard to test automatically whether your code writes appropriate log entries. First you have to parse the log files, and second you have to find the right moment to do so as the log is written asynchronous. Access to external web services is a second source of confusion, since it is usually outside of the scope of a test environment and therefore not controlled and not reproducible. Instead of accessing these resources directly, you can define an interface for the resource and use it instead. Then you can use stubs or mocks during tests.
But how do you know whether you run in the context of a test? You don’t have to. Avoid creating instances of collaborating resources inside your implementation. Let someone on the outside do this for you.
The Microsoft Patterns & Practices recommend using the Service Locator pattern for this. A Service Locator is a class with static properties, where someone stores a resource and later someone else gets it. Outside the SharePoint world, this is well known as an anti pattern. First, the usage of resources is not transparent. You cannot see which resources a class needs without looking at the implementation. This yields surprising errors in tests when the implementation changes. If a reference to an additional resource is added, the test compiles just fine, but no one adds the respective implementation to the Service Locator and the test fails at runtime. Second, all resources have to be re-initialized before each test run, because you don’t know whether the previous tests changed something.
Outside of SharePoint, the most common solution is dependency injection. The most simple way is to pass all resources as arguments to the constructor. You could also inject resources to properties of the object, if you have no control over its construction. This way each class clearly states its dependencies and the external code is responsible for satisfying these. You usually use a dependency injection container such as Ninject. You register all kinds of resources with your container, and the container will resolve the dependency chains at runtime. For automated tests you can also use a combination of AutoFixture and Moq to resolve all dependencies using mock objects.
SharePoint does not support dependency injection by default. Controls, Pages and all other framework objects are created somewhere inside SharePoint with no way to inject additional parameters into the constructor. The same issue appears in ASP.NET, so you can have a look at the solutions there. Ninject.Web provides base classes for property based dependency injection. You can do the same for SharePoint base classes, which call Inject(this) in their constructor.
We developed and implemented the dependency injection helper classes at adesso. We might publish the implementation, be it open or closed source, but this is still undecided. If you are interested in this, please leave a comment. I am not the one who decides, but we are actively seeking opinions on this, so you will actually influence the outcome.