From Martin Fowler's Mocks Aren't Stubs he states that Stubs provide canned answers to calls made during the test while Mocks objects pre-programmed with expectations which form a specification of the calls they are expected to receive.
In addition several sources state that Stubs shouldn't fail tests, but Mock could.
So what about this:
$validator= $this->getMock('ValidatorService'); // Set up the expectation for the isValid() method // to be called only once and with the string 'textToBeValidated' // as its parameter and returns true or false. $validator->expects($this->once()) ->method('isValid') ->with($this->equalTo('textToBeValidated')) ->will($this->returnValue(true));
This came up in a code review in a project I'm working on and we called it a Stock (St ub - M ock). Why you ask?!
- It set an expectation for
isValid()to be called only once and with certain input like a Mock.
- It returns a canned answer like a Stub.
I get a feeling that this is wrong, but what if we used a pure Stub only:
$validator->expects($this->any()) //<-- can't fail the test now ->method('isValid') ->will($this->returnValue(true)); //<-- canned answer
- I can't verify that the method
isValidwas called only once with the right parameters.
- If the test passed I'm not sure that it passed for the right reason. Maybe
isValid()was called twice and that caused it to pass.
So let's use a pure Mock instead:
$validator->expects($this->once()) ->method('isValid') ->with($this->equalTo('textToBeValidated'))
- I can't verify that my function works correctly, because I only verified that call to
isValid()was successful. Maybe there is a bug in the rest of my code using the
I know some people will talk about state vs behavior verification, but the way I see it the only way to be sure that the test passes for the correct reason is to to use a Stock (i.e. verify the behavior and final state).
Of course the other option is to write 2 test for every test criteria. One using a Mock and an identical test using a Stub. However, that will result in a TestOverflow (a huge number of nearly identical tests).
What is the correct way to have a concrete test of a function using a dependency?