A partial mock is simply a pattern to alleviate a specific problem in testing with mock objects, that of getting mock objects into tight corners. It's quite a limited tool and possibly not even a good idea. It is included with SimpleTest because I have found it useful on more than one occasion and has saved a lot of work at that point.
When one object uses another it is very simple to just pass a mock version in already set up with its expectations. Things are rather tricker if one object creates another and the creator is the one you want to test. This means that the created object should be mocked, but we can hardly tell our class under test to create a mock instead. The tested class doesn't even know it is running inside a test after all.
For example, suppose we are building a telnet client and it
needs to create a network socket to pass its messages.
The connection method might look something like...
The first solution is to pass the socket in as a parameter, forcing the creation up a level. Having the client handle this is actually a very good approach if you can manage it and should lead to factoring the creation from the doing. In fact, this is one way in which testing with mock objects actually forces you to code more tightly focused solutions. They improve your programming.
Here this would be...
The next simplest compromise is to have the created object passed
in as an optional parameter...
The next method is to pass in a factory object to do the creation...
Is there a middle ground?
There is a way we can circumvent the problem without creating
any new application classes, but it involves creating a subclass
when we do the actual testing.
Firstly we move the socket creation into its own method...
For the test case we have to create a subclass so that
we can intercept the socket creation...
connect().
Otherwise it could get a null value from
_createSocket().
After the completion of all of this extra work the
actual test case is fairly easy.
We just test our new class instead...
Of course the answer is "yes" or I would have stopped writing this by now! The previous test case was a lot of work, but we can generate the subclass using a similar approach to the mock objects.
Here is the partial mock version of the test...
generatePartial() call
takes three parameters: the class to be subclassed,
the new test class name and a list of methods to mock.
Instantiating the resulting objects is slightly tricky. The only constructor parameter of a partial mock is the unit tester reference. As with the normal mock objects this is needed for sending test results in response to checked expectations.
The original constructor is not run yet. This is necessary in case the constructor is going to make use of the as yet unset mocked methods. We set any return values at this point and then run the constructor with its normal parameters. This three step construction of "new", followed by setting up the methods, followed by running the constructor proper is what distinguishes the partial mock code.
Apart from construction, all of the mocked methods have
the same features as mock objects and all of the unmocked
methods behave as before.
We can set expectations very easily...
The mocked out methods don't have to be factory methods, they could be any sort of method. In this way partial mocks allow us to take control of any part of a class except the constructor. We could even go as far as to mock every method except one we actually want to test.
This last situation is all rather hypothetical, as I haven't tried it. I am open to the possibility, but a little worried that forcing object granularity may be better for the code quality. I personally use partial mocks as a way of overriding creation or for occasional testing of the TemplateMethod pattern.
It's all going to come down to the coding standards of your project to decide which mechanism you use.