sebastianbergmann / phpunit-mock-objects
- Source
- Commits
- Network (4)
- Issues (17)
- Graphs
-
Branch:
master
click here to add a description
click here to add a homepage
-
0 comments Created 3 months ago by sebastianbergmannMock API: $this->at() without arguments increments internallyfeature request -
1 comment Created 3 months ago by sebastianbergmannMake it possible to use mocked methods in object's constructorfeature requestCopied from http://www.phpunit.de/ticket/971
Comments
Please log in to comment.whatthejeff Sun Aug 08 18:27:54 -0700 2010 | linkThis is actually possible already. I suspect this is why the programmer has the option to suppress calls to the constructor when mocking an object. For instance, the code from this ticket could be modified to work as follows:
<?php class O { public function __construct() { $this->useFoo(); } protected function getFoo() { return 'foo'; } protected function useFoo() { if ($this->getFoo() === 'bar') { $this->ok(); } } protected function ok() { } } class FooTest extends PHPUnit_Framework_TestCase { public function testFoo() { $mock = $this->getMock('O', array('getFoo', 'ok'), array(), '', FALSE); $mock->expects($this->any()) ->method('getFoo') ->will($this->returnValue('bar')); $mock->expects($this->once()) ->method('ok'); $mock->__construct(); } } -
0 comments Created 3 months ago by sebastianbergmannSupport parameters passed by reference when using returnCallbackfeature request -
1 comment Created 3 months ago by sebastianbergmannCannot modify the return value of a mocked methodbugCopied from http://www.phpunit.de/ticket/936
Comments
Please log in to comment.whatthejeff Sun Aug 08 19:36:00 -0700 2010 | linkI think this is expected behavior. It doesn't make sense to set up two conflicting expectations. You can not say that any call to
OpenID_Assertion_Result::success()is expected to returntrueandfalsein the same test. That doesn't really make sense.What you want to use is
PHPUnit_Framework_TestCase::at(). For example, the following code will yield the expected results:<?php class MyTest extends PHPUnit_Framework_TestCase { public function testChangingReturnValue() { $mock = $this->getMock('OpenID_Assertion_Result', array('success'), array(), '', false); $mock->expects($this->at(0)) ->method('success') ->will($this->returnValue(false)); $mock->expects($this->at(1)) ->method('success') ->will($this->returnValue(true)); $this->assertFalse($mock->success()); $this->assertTrue($mock->success()); } } ?>A more robust solution for a method that might accept and return a number of different values is to use
PHPUnit_Framework_TestCase::returnCallback(). This enables you to define a method that accepts calls on behalf of your mocked method. -
Copied from http://www.phpunit.de/ticket/934
Comments
This probably isn't the correct place for this but nonetheess I have worked around this problem by using a closure. I delved briefly into actually patching PHPUnit but it's pretty tricky.
Some sort of "how to hack on phpunit" would be good - I'd be happy to try and fix this with some guidance.
The workaround:
$this->App->expects($this->any())->method("renderPartial")->will($this->returnCallback(function($arg1) use ($test, $template) { $test->assertNotEquals($template, $arg1, "renderPartial should never be called with $template"); }));Please log in to comment.whatthejeff Sun Aug 08 21:22:00 -0700 2010 | linkThis isn't really a bug, but the
PHPUnit_Framework_ExpectationFailedExceptionexception could definitely do a better job at telling you why your test has failed. You must understand thatPHPUnit_Framework_TestCase::never()andPHPUnit_Framework_MockObject_Builder_InvocationMocker::with()are not working together. They are two separate assertions.Think of
PHPUnit_Framework_TestCase::never(),PHPUnit_Framework_TestCase::any(),PHPUnit_Framework_TestCase::exactly(), and the other invocation recorders as a simple assertion on the number of times a method will be invoked.PHPUnit_Framework_TestCase::never()asserts that your method will be invoked 0 times. In your case, this assertion passes.Think of
PHPUnit_Framework_MockObject_Builder_InvocationMocker::with()as a completely separate assertion that verifies that a method is invoked with parameters that match a certain set of conditions. Obviously if your method is never invoked then this assertion can never pass. This might not be too obvious with the message "Mocked method does not exist." I think something like, "Parameters do not match since mocked method was never invoked," would be a little bit more clear.As a side note, it's possible to use
PHPUnit_Framework_Assert::logicalNot()in combination withPHPUnit_Framework_MockObject_Builder_InvocationMocker::with()to negate assertions about parameters. A more robust solution would be to usePHPUnit_Framework_TestCase::returnCallback()and add assertions about expected parameters in your callback. -
1 comment Created 3 months ago by sebastianbergmannCheck method call with different parametersfeature requestCopied from http://www.phpunit.de/ticket/901
Comments
Please log in to comment.whatthejeff Sun Aug 08 21:59:28 -0700 2010 | linkThis is not really how the mocking system works in PHPUnit. Two mistakes are being made in this example code.
- You can not combine
PHPUnit_Framework_TestCase::never()andPHPUnit_Framework_TestCase::any()for the same method in a single test.
» More information here - You can not use
PHPUnit_Framework_TestCase::never()to negatePHPUnit_Framework_MockObject_Builder_InvocationMocker::with().
» More information here
You are looking for something like
PHPUnit_Framework_TestCase::returnCallback(). For example:<?php class ExampleTest extends PHPUnit_Framework_TestCase { public function testProduct() { $product = $this->getMock('Model_Row_Product'); $product->expects($this->any()) ->method('__get') ->will($this->returnCallback(array($this, 'get'))); $price = $this->calculator->calculate($product); } public function get($key) { switch($key) { case 'tbRetailPrice': return 10.1; case 'tbWholesalePrice': $this->fail("Unexpected value '$key'"); } } } ?> - You can not combine
-
Copied from http://www.phpunit.de/ticket/873
Comments
Please log in to comment.whatthejeff Sun Aug 15 05:49:56 -0700 2010 | linkThe original description of this ticket is a little vague. Basically the author has created a situation where the
__clone()method calls itself indefinitely. I've included a simpler example below:<?php class A { private $stack; public function setStack(SplStack $stack) { $this->stack = $stack; $this->stack->push($this); } public function __clone() { $this->setStack($this->stack); } } class ATest extends PHPUnit_Framework_TestCase { public function testSetStack() { $a = new A(); $a->setStack($this->getMock('SplStack')); } }The
A::setStack()method is problematic as it is called from the__clone()method but also triggers the__clone()method by passing$thisas a parameter to a mocked method.This is related to Issue 16 and does raise the question if cloning parameters to mocked methods should be the default behavior.
-
0 comments Created 3 months ago by sebastianbergmannMake stubbing/mocking API public or staticfeature request -
1 comment Created 3 months ago by sebastianbergmannMake a test fail if a mocked method is not expected to be invokedfeature requestCopied from http://www.phpunit.de/ticket/854
Comments
Please log in to comment.whatthejeff Mon Aug 09 20:18:08 -0700 2010 | linkMaking a change like this would break many existing tests. Remember that
PHPUnit_Framework_TestCase::getMock()is not only used for creating mocks, but for the entire spectrum of test doubles.If you read http://www.phpunit.de/manual/current/en/test-doubles.html, this is expected behavior. By default
PHPUnit_Framework_TestCase::getMock()returns a stub object that just returns null for all methods. It's really up to you as the programmer to decide how to use this object. To force a programmer to mock every possible invocation of every method in this object would be unreasonable in many situations.For what it's worth, the invocation recorders like
PHPUnit_Framework_TestCase::once()andPHPUnit_Framework_TestCase::exactly()are set up specifically for the type of situation you are describing. If you want to assert that a mocked method is only called once, you should usePHPUnit_Framework_TestCase::once(). -
0 comments Created 3 months ago by sebastianbergmannSpecifying multiple invocations for MockObject (next to) impossiblefeature request -
3 comments Created 3 months ago by sebastianbergmannMultiple calls on same method with different parameters does not workbugCopied from http://www.phpunit.de/ticket/820
Comments
Is there a known way to work around this issue? It doesn't seem such an unusual case.
Just in case someone cares: I've worked around this by using returnCallback() on the mocked magic get() and set(), and have the callback function mock getter and setter behavior.
Please log in to comment.whatthejeff Mon Aug 09 20:54:59 -0700 2010 | linkThis is really similar to issue 4 and issue 6. Basically you need to use
PHPUnit_Framework_TestCase::at()orPHPUnit_Framework_TestCase::returnCallback(). It seems a lot of tickets reference this issue in one way or another. Maybe the docs should be updated to explain exactly how to approach situations like this. -
0 comments Created 3 months ago by sebastianbergmannAbility to Turn on Errors for mocking non-existant classes/methodsfeature request -
0 comments Created 3 months ago by sebastianbergmannUsing callback function on with() call to be able to check different parametersfeature request -
0 comments Created 3 months ago by sebastianbergmannNo result is returned if parameters are checked prior to definition of resultbug -
0 comments Created 3 months ago by sebastianbergmannClass Posing support for Mock Objectsfeature request -
1 comment Created 3 months ago by sebastianbergmannReferencing objects to compare failes if object is modified when cloned using mock objectsbugCopied from http://www.phpunit.de/ticket/120
Comments
Please log in to comment.The logic on that ticket doesn't really follow for object identity. Whether you compare the object passed immediately or at tear-down time, it's the same object.
If the object was modified later in execution, then of course the handle that the test has on the object will also have been modified, and it doesn't make sense for the handle in the Mock to lag behind.
Furthermore, I'd suggest if this sort of modification is likely, your SUT may be too wide for a single test case anyway.
Generally I believe that if I were to write:
$mock->expects($this->once()) ->method('aMethod') ->with($this->identicalTo($obj)); $mock->aMethod($obj);... in a test case, it should not fail.
-
0 comments Created 3 months ago by sebastianbergmannSupport sequential sets of parameters in a stubbed method callfeature request


