On Friday, December 14, 2012 3:37:28 PM UTC+1, Mike Lively wrote:
I am not entirely sure what your first question is driving towards. Phake should not through exceptions unless you:
stub a method to throw an exception [ http://phake.digitalsandwich.com/docs/html/answers.html#d5e357 ]
stub a method to call the actual method of the mocked class [ http://phake.digitalsandwich.com/docs/html/ch04s02.html ]
there is a bug in phake [ https://github.com/mlively/Phake/issues ]
In any of these cases the exception will (presumably) be thrown when you invoke the code being tested. If this exception is something that you are not catching in the system under test (SUT) and if you are wanting to verify that the stubbed exception is getting thrown then you can $this->setExpectedException() or the @expectedException annotation in phpunit. If you are wanting to verify function calls on the mock, then you would need to manually catch the exception. I have found that when I am stubbing a class to throw an exception that the purpose of that is to test that my SUT has proper error handling in place. I could see a few scenarios where what you are saying could apply though I haven't ran into them myself yet. If you wouldn't mind elaborating or giving me a more detailed use case that would be great. Everyone's experience is a little different and I would love to dig into yours a little bit. Talking about a solution without fully understanding the problem is a little bit difficult, but I can say that I would avoid moving verification into destructors. The call order of destructors can at times be unpredictable which makes them somewhat difficult to diagnose if you have problems. Also, setExpectedException() should work. I frequently use it myself.
First, let me thank you for replying quickly. I can give you an example of the first question.
[Code is just a mockup]
public function testShouldThrowAnException ()
{
$this->setExpectedException('SomeException', 'Message', 404);
$path = Phake::mock('Path');
Phake::when($path)->exists(Phake::anyParameters)->thenReturn(FALSE);
$object = new Route($path);
$object->navigate('not_index');
Phake::verify($path)->exists(Phake::anyParameters);
}
class Path
{
public function exists ($page)
{
return $page == 'index';
}
}
class Route
{
public function __construct (Path $p)
{
$this->p = $p;
}
public function navigate ($page)
{
// Oh noes! Mock object is not used:
if (FALSE or !$this->p->exists($page))
{
throw new SomeException('Message', 404);
}
}
}
The problem here is that even though the test passes, the mock object is not used nor verbose about it not being used.
So the only solution here is to write a try-catch block around the tested code?
There are not any plans to implement an alternative syntax for declaring the number of times explicitly as you outline here.
I am not sure how familiar you are with the existing consecutive calls syntax. It is basically what you have below, you just don't specify the 'times()'. You can read more about this functionality at http://phake.digitalsandwich.com/docs/html/stubbing-consecutive-calls.html
If you are more so looking for ways to combine stubbing and verification my first reaction would be to try to steer you away from doing that. One of the primary reason's I created Phake and really one of the driving solutions is to treat mocks with the same fixture / verification treatment that most other unit testing concepts follow. I can go into this in more depth if you are interested but I am not sure that is what you are driving towards with this question. Let me know!
Yes, I would want to hear about why combining stubbing and verification isn't recommended. Again, I'm originally used to the way PHPUnit Mock objects handle verification, so my knowledge is pretty shallow regarding this subject. The feeling I have is, the stub has been configured behave in a particular way. Couldn't that configuration be verified automatically then?
(Or would it be truly impossible without implementing the ugly ->at(0) ->at(1) ... syntax?)
Hope to hear from you soon.