One of the major differences between interaction based and state based testing is the level that you are testing the code. State based testing is testing results of an operation, interaction based testing tests the operation itself. This means that you can get into situations where you are atrophied by the tests. Any change to the code causes a cascading affect on all the tests.
Here are some guidelines that should help in this regard. They all boil down to "A Test Should Check Only One Thing". This means that we need a distinction here. We have fake objects, which are created just so we can give the test the data it needs. And then we have mocks, which are used to verify the behavior of the test.
In general, there should be as few mocks as possible, preferably one. All the other collaborators should be fakes.
For mock objects, you should use the full power of the mocking framework to setup detailed expectations about what should happen. For fake objects, you should make sure that as much as possible, they will not break the tests.
For Rhino Mocks, this means that fake objects should:
- Prefer to use DynamicMock over CreateMock
- Use SetupResult over Expect or LastCall
Using both of those should reduce the number of expectations that the test should meet. Remember a test should have only one thing that can fail it.