diff --git a/CHANGELOG.md b/CHANGELOG.md index c59833506..a767aeb74 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,17 +17,23 @@ argument from both `spy()` and `stub()` ([#123]). - **[BC BREAK]** Removed the `$self` and `$defaultAnswerCallback` arguments from `stub()` ([#123]). +- **[BC BREAK]** Rewrite and rename of mock builder API methods for creating + mocks ([#103]). - **[IMPROVED]** Made API setter style methods fluent ([#98]). - **[IMPROVED]** Instance handles are automatically adapted when stubbing and verifying ([#126]). - **[IMPROVED]** Added checks for unused stub criteria ([#126]). +- **[IMPROVED]** Default answer callbacks are now a first-class concept for + mocks ([#90]). - **[FIXED]** Fixed bug when mocking traits with magic call methods ([#127]). - **[FIXED]** Mocking, and calling of return-by-reference methods no longer causes errors to be emitted ([#105]). - **[FIXED]** Ad-hoc mocks that differ only by function body no longer result in re-use of the same mock class ([#131]). +[#90]: https://github.com/eloquent/phony/issues/90 [#98]: https://github.com/eloquent/phony/issues/98 +[#103]: https://github.com/eloquent/phony/issues/103 [#105]: https://github.com/eloquent/phony/issues/105 [#117]: https://github.com/eloquent/phony/issues/117 [#123]: https://github.com/eloquent/phony/issues/123 diff --git a/doc/index.md b/doc/index.md index 5807a5709..4eb06861f 100644 --- a/doc/index.md +++ b/doc/index.md @@ -47,6 +47,7 @@ - [Multiple answers] - [Overriding rules] - [The default rule and answer] + - [The default answer callback] - [Matching stub arguments] - [Returning values] - [Returning arguments] @@ -531,6 +532,24 @@ Turn the mock into a [full mock]. Turn the mock into a [partial mock]. + + +---- + +> *callable* $handle->[**defaultAnswerCallback**](#handle.defaultAnswerCallback)() + +Get the [default answer callback]. + + + +---- + +> *fluent* $handle->[**setDefaultAnswerCallback**](#handle.setDefaultAnswerCallback)($callback) + +Set the [default answer callback] for all method stubs of this mock. + +*This method accepts a callback that takes the stub as the first argument.* + ---- @@ -718,33 +737,31 @@ Get a mock. *This method will return the last created mock, only creating a new mock if no existing mock is available.* +*If no existing mock is available, the created mock will be a full mock.* + *Calling this method will finalize the mock builder.* *See [Creating mocks from a builder].* - + ---- -> *mock* $builder->[**create**](#builder.create)(...$arguments) - -Create a new [partial mock]. +> *mock* $builder->[**full**](#builder.full)() -*The constructor will be called with `$arguments`.* +Create a new [full mock]. *This method will always create a new mock.* *Calling this method will finalize the mock builder.* -*This method does not support reference parameters.* - *See [Creating mocks from a builder].* - + ---- -> *mock* $builder->[**createWith**](#builder.createWith)($arguments = [], $label = null) +> *mock* $builder->[**partial**](#builder.partial)(...$arguments) Create a new [partial mock]. @@ -754,22 +771,27 @@ Create a new [partial mock]. *Calling this method will finalize the mock builder.* -*This method supports reference parameters.* +*This method does not support reference parameters.* *See [Creating mocks from a builder].* - + ---- -> *mock* $builder->[**full**](#builder.full)() +> *mock* $builder->[**partialWith**](#builder.partialWith)($arguments = [], $label = null) -Create a new [full mock]. +Create a new [partial mock]. + +*The constructor will be called with `$arguments`, unless `$arguments` is +`null`, in which case the constructor will not be called at all.* *This method will always create a new mock.* *Calling this method will finalize the mock builder.* +*This method supports reference parameters.* + *See [Creating mocks from a builder].* ### Mocking basics @@ -1343,36 +1365,36 @@ available methods, see [the mock builder API]. #### Creating mocks from a builder -Once the builder is configured, there are several options for generating the -mock class, or creating mock instances. All of these will internally "finalize" -the mock builder, and no further customizations can be made. +Once the builder is configured, there are several options for creating mock +instances. All of these will internally "finalize" the mock builder, and no +further customizations can be made. -Use [`create()`](#builder.create) to create a new mock instance: +Use [`full()`](#builder.full) to create a new full mock instance: ```php -$mock = $builder->create(); +$mock = $builder->full(); ``` -Constructor arguments can also be passed to [`create()`](#builder.create): +Use [`partial()`](#builder.partial) to create a new partial mock instance: ```php -$mock = $builder->create('a', 'b'); +$mock = $builder->partial(); ``` -There is also a more advanced method, [`createWith()`](#builder.createWith), -that accepts arguments passed by reference: +Constructor arguments can also be passed to [`partial()`](#builder.partial): ```php -$a = null; -$b = null; - -$mock = $builder->createWith([&$a, &$b]); +$mock = $builder->partial('a', 'b'); ``` -To create a new "full" mock instance, use [`full()`](#builder.full): +There is also a more advanced method, [`partialWith()`](#builder.partialWith), +that accepts arguments passed by reference: ```php -$mock = $builder->full(); +$a = null; +$b = null; + +$mock = $builder->partialWith([&$a, &$b]); ``` All of the above methods for creating mock instances store the last created mock @@ -1380,14 +1402,14 @@ instance on the builder. To retrieve the last created mock instance, use [`get()`](#builder.get): ```php -$mockA = $builder->create(); +$mockA = $builder->full(); $mockB = $builder->get(); echo $mockA === $mockB ? 'true' : 'false'; // outputs 'true' ``` -If no mock instance already exists, [`get()`](#builder.get) will create one and -return it. +If no mock instance already exists, [`get()`](#builder.get) will create a new +full mock instance, and return it. Note that unlike using [`mock()`](#facade.mock), these methods do not automatically wrap the returned mock in a [mock handle]. To obtain a stubbing @@ -1426,6 +1448,9 @@ generate the mock class, and return the class name as a string: $className = $builder->className(); ``` +All of the above methods will internally "finalize" the mock builder, and no +further customizations can be made. + ### Terminology By some popular definitions, *Phony*'s mocks are not technically mocks at all, @@ -1515,6 +1540,24 @@ Get the [self value] of this stub. Set the [self value] of this stub. + + +---- + +> *callable* $stub->[**defaultAnswerCallback**](#stub.defaultAnswerCallback)() + +Get the [default answer callback]. + + + +---- + +> *fluent* $stub->[**setDefaultAnswerCallback**](#stub.setDefaultAnswerCallback)($callback) + +Set the [default answer callback] of this stub. + +*This method accepts a callback that takes the stub as the first argument.* + ---- @@ -2495,19 +2538,49 @@ $stubB = stub() ``` If a new rule is started before any answers are defined, the stub behaves as if -[`returns()`](#stub.returns) were called, causing the stub to return `null` by -default. For example, the two following stubs behave the same: +[`forwards()`](#stub.forwards) were called, causing the stub to behave the same +as the stubbed callable by default. For example, the two following stubs behave +the same: ```php -$stubA = stub() - ->with('*')->returns() +$stubA = stub($callable) + ->with('*')->forwards() ->with('a')->returns('x'); -$stubB = stub() - // implicit ->with('*')->returns() +$stubB = stub($callable) + // implicit ->with('*')->forwards() ->with('a')->returns('x'); ``` +##### The default answer callback + +To change the default behavior of a stub, use +[`setDefaultAnswerCallback()`](#stub.setDefaultAnswerCallback). This method +accepts a callback that takes the stub as the first argument: + +```php +$stub = stub(); +$stub->setDefaultAnswerCallback( + function ($stub) { + // custom answer logic goes here + $stub->returns('default'); + } +); + +$stub->with('a')->returns('x'); + +echo $stub('a'); // outputs 'x' +echo $stub('b'); // outputs 'default' +``` + +The [`setDefaultAnswerCallback()`](#stub.setDefaultAnswerCallback) method is +also fluent, meaning stub creation and setting of this option can be done in a +single expression: + +```php +$stub = stub()->setDefaultAnswerCallback($defaultAnswerCallback); +``` + ### Matching stub arguments Stub arguments can be matched using [`with()`](#stub.with) (not to be confused @@ -6097,6 +6170,7 @@ For the full copyright and license information, please view the [LICENSE file]. [the "wildcard" matcher]: #the-wildcard-matcher [the arguments api]: #the-arguments-api [the call api]: #the-call-api +[the default answer callback]: #the-default-answer-callback [the default rule and answer]: #the-default-rule-and-answer [the event api]: #the-event-api [the export format]: #the-export-format @@ -6158,6 +6232,7 @@ For the full copyright and license information, please view the [LICENSE file]. ["equal to" matcher]: #the-equal-to-matcher ["wildcard" matcher]: #the-wildcard-matcher [ad hoc mock]: #ad-hoc-mocks +[default answer callback]: #the-default-answer-callback [full mock]: #mocking-basics [generator spies]: #verifying-spies-with-generators-or-traversables [matcher]: #matchers diff --git a/src/Mock/Builder/Factory/MockBuilderFactory.php b/src/Mock/Builder/Factory/MockBuilderFactory.php index db0dc8487..3fff73f0a 100644 --- a/src/Mock/Builder/Factory/MockBuilderFactory.php +++ b/src/Mock/Builder/Factory/MockBuilderFactory.php @@ -137,7 +137,7 @@ public function createPartialMock($types = array(), $arguments = array()) $builder = new MockBuilder($types, $this->mockFactory, $this->proxyFactory); - return $builder->createWith($arguments); + return $builder->partialWith($arguments); } private static $instance; diff --git a/src/Mock/Builder/MockBuilder.php b/src/Mock/Builder/MockBuilder.php index f3bb10ae5..f4702fe08 100644 --- a/src/Mock/Builder/MockBuilder.php +++ b/src/Mock/Builder/MockBuilder.php @@ -484,6 +484,8 @@ public function className($createNew = false) * This method will return the current mock, only creating a new mock if no * existing mock is available. * + * If no existing mock is available, the created mock will be a full mock. + * * Calling this method will finalize the mock builder. * * @return MockInterface The mock instance. @@ -495,68 +497,67 @@ public function get() return $this->mock; } - $this->mock = $this->factory->createMock($this, array()); + $this->mock = $this->factory->createFullMock($this); return $this->mock; } /** - * Create a new mock. + * Create a new full mock. * * This method will always create a new mock, and will replace the current * mock. * * Calling this method will finalize the mock builder. * - * @param mixed ...$arguments The constructor arguments. - * * @return MockInterface The mock instance. * @throws MockExceptionInterface If the mock generation fails. */ - public function create() + public function full() { - $this->mock = $this->factory->createMock($this, func_get_args()); + $this->mock = $this->factory->createFullMock($this); return $this->mock; } /** - * Create a new mock. + * Create a new partial mock. * * This method will always create a new mock, and will replace the current * mock. * * Calling this method will finalize the mock builder. * - * This method supports reference parameters. - * - * @param ArgumentsInterface|array|null $arguments The constructor arguments, or null to bypass the constructor. + * @param mixed ...$arguments The constructor arguments. * * @return MockInterface The mock instance. * @throws MockExceptionInterface If the mock generation fails. */ - public function createWith($arguments = array()) + public function partial() { - $this->mock = $this->factory->createMock($this, $arguments); + $this->mock = $this->factory->createPartialMock($this, func_get_args()); return $this->mock; } /** - * Create a new full mock. + * Create a new partial mock. * * This method will always create a new mock, and will replace the current * mock. * * Calling this method will finalize the mock builder. * + * This method supports reference parameters. + * + * @param ArgumentsInterface|array|null $arguments The constructor arguments, or null to bypass the constructor. + * * @return MockInterface The mock instance. * @throws MockExceptionInterface If the mock generation fails. */ - public function full() + public function partialWith($arguments = array()) { - $this->mock = $this->factory->createMock($this, null); - $this->proxyFactory->createStubbing($this->mock)->full(); + $this->mock = $this->factory->createPartialMock($this, $arguments); return $this->mock; } diff --git a/src/Mock/Builder/MockBuilderInterface.php b/src/Mock/Builder/MockBuilderInterface.php index 3ef696f8b..fb90ea10c 100644 --- a/src/Mock/Builder/MockBuilderInterface.php +++ b/src/Mock/Builder/MockBuilderInterface.php @@ -198,6 +198,8 @@ public function className($createNew = false); * This method will return the current mock, only creating a new mock if no * existing mock is available. * + * If no existing mock is available, the created mock will be a full mock. + * * Calling this method will finalize the mock builder. * * @api @@ -208,7 +210,7 @@ public function className($createNew = false); public function get(); /** - * Create a new mock. + * Create a new full mock. * * This method will always create a new mock, and will replace the current * mock. @@ -217,12 +219,10 @@ public function get(); * * @api * - * @param mixed ...$arguments The constructor arguments. - * * @return MockInterface The mock instance. * @throws MockExceptionInterface If the mock generation fails. */ - public function create(); + public function full(); /** * Create a new mock. @@ -232,31 +232,33 @@ public function create(); * * Calling this method will finalize the mock builder. * - * This method supports reference parameters. - * * @api * - * @param ArgumentsInterface|array|null $arguments The constructor arguments, or null to bypass the constructor. + * @param mixed ...$arguments The constructor arguments. * * @return MockInterface The mock instance. * @throws MockExceptionInterface If the mock generation fails. */ - public function createWith($arguments = array()); + public function partial(); /** - * Create a new full mock. + * Create a new mock. * * This method will always create a new mock, and will replace the current * mock. * * Calling this method will finalize the mock builder. * + * This method supports reference parameters. + * * @api * + * @param ArgumentsInterface|array|null $arguments The constructor arguments, or null to bypass the constructor. + * * @return MockInterface The mock instance. * @throws MockExceptionInterface If the mock generation fails. */ - public function full(); + public function partialWith($arguments = array()); /** * Get the generated source code of the mock class. diff --git a/src/Mock/Factory/MockFactory.php b/src/Mock/Factory/MockFactory.php index 6a6a5f2ab..f083dcefd 100644 --- a/src/Mock/Factory/MockFactory.php +++ b/src/Mock/Factory/MockFactory.php @@ -180,10 +180,7 @@ public function createMockClass( $customMethodsProperty->setAccessible(true); $customMethodsProperty->setValue(null, $customMethods); - $proxyProperty = $class->getProperty('_staticProxy'); - $proxyProperty->setAccessible(true); - $proxyProperty - ->setValue(null, $this->proxyFactory->createStubbingStatic($class)); + $this->proxyFactory->createStubbingStatic($class); $this->definitions[] = array($definition, $class); @@ -191,7 +188,24 @@ public function createMockClass( } /** - * Create a new mock instance for the supplied builder. + * Create a new full mock instance for the supplied builder. + * + * @param MockBuilderInterface $builder The builder. + * + * @return MockInterface The newly created mock. + * @throws MockExceptionInterface If the mock generation fails. + */ + public function createFullMock(MockBuilderInterface $builder) + { + $mock = $builder->build()->newInstanceArgs(); + $this->proxyFactory + ->createStubbing($mock, strval($this->labelSequencer->next())); + + return $mock; + } + + /** + * Create a new partial mock instance for the supplied builder. * * @param MockBuilderInterface $builder The builder. * @param ArgumentsInterface|array|null $arguments The constructor arguments, or null to bypass the constructor. @@ -199,18 +213,15 @@ public function createMockClass( * @return MockInterface The newly created mock. * @throws MockExceptionInterface If the mock generation fails. */ - public function createMock( + public function createPartialMock( MockBuilderInterface $builder, $arguments = array() ) { - $class = $builder->build(); - $mock = $class->newInstanceArgs(); + $mock = $builder->build()->newInstanceArgs(); $proxy = $this->proxyFactory ->createStubbing($mock, strval($this->labelSequencer->next())); - $proxyProperty = $class->getProperty('_proxy'); - $proxyProperty->setAccessible(true); - $proxyProperty->setValue($mock, $proxy); + $proxy->partial(); if (null !== $arguments) { $proxy->constructWith($arguments); diff --git a/src/Mock/Factory/MockFactoryInterface.php b/src/Mock/Factory/MockFactoryInterface.php index a29a14bae..c9a3bcfed 100644 --- a/src/Mock/Factory/MockFactoryInterface.php +++ b/src/Mock/Factory/MockFactoryInterface.php @@ -37,7 +37,17 @@ public function createMockClass( ); /** - * Create a new mock instance for the supplied builder. + * Create a new full mock instance for the supplied builder. + * + * @param MockBuilderInterface $builder The builder. + * + * @return MockInterface The newly created mock. + * @throws MockExceptionInterface If the mock generation fails. + */ + public function createFullMock(MockBuilderInterface $builder); + + /** + * Create a new partial mock instance for the supplied builder. * * @param MockBuilderInterface $builder The builder. * @param ArgumentsInterface|array|null $arguments The constructor arguments, or null to bypass the constructor. @@ -45,7 +55,7 @@ public function createMockClass( * @return MockInterface The newly created mock. * @throws MockExceptionInterface If the mock generation fails. */ - public function createMock( + public function createPartialMock( MockBuilderInterface $builder, $arguments = array() ); diff --git a/src/Mock/Proxy/AbstractProxy.php b/src/Mock/Proxy/AbstractProxy.php index 67b955f28..ee9c74feb 100644 --- a/src/Mock/Proxy/AbstractProxy.php +++ b/src/Mock/Proxy/AbstractProxy.php @@ -31,7 +31,6 @@ use Eloquent\Phony\Stub\Factory\StubFactoryInterface; use Eloquent\Phony\Stub\Factory\StubVerifierFactory; use Eloquent\Phony\Stub\Factory\StubVerifierFactoryInterface; -use Eloquent\Phony\Stub\StubInterface; use Eloquent\Phony\Stub\StubVerifierInterface; use ReflectionClass; use ReflectionMethod; @@ -72,8 +71,9 @@ public function __construct( ) { if (null === $state) { $state = (object) array( + 'defaultAnswerCallback' => + 'Eloquent\Phony\Stub\Stub::returnsNullAnswerCallback', 'stubs' => (object) array(), - 'isFull' => false, ); } if (null === $stubFactory) { @@ -194,7 +194,8 @@ public function className() */ public function full() { - $this->state->isFull = true; + $this->state->defaultAnswerCallback = + 'Eloquent\Phony\Stub\Stub::returnsNullAnswerCallback'; return $this; } @@ -206,19 +207,38 @@ public function full() */ public function partial() { - $this->state->isFull = false; + $this->state->defaultAnswerCallback = + 'Eloquent\Phony\Stub\Stub::forwardsAnswerCallback'; return $this; } /** - * Returns true if the mock is a full mock. + * Set the callback to use when creating a default answer. * - * @return boolean True if the mock is a full mock. + * @api + * + * @param callable $defaultAnswerCallback The default answer callback. + * + * @return $this This proxy. + */ + public function setDefaultAnswerCallback($defaultAnswerCallback) + { + $this->state->defaultAnswerCallback = $defaultAnswerCallback; + + return $this; + } + + /** + * Get the default answer callback. + * + * @api + * + * @return callable The default answer callback. */ - public function isFull() + public function defaultAnswerCallback() { - return $this->state->isFull; + return $this->state->defaultAnswerCallback; } /** @@ -360,20 +380,6 @@ public function state() return $this->state; } - /** - * Create the default answer for the supplied stub. - * - * @param StubInterface $stub The stub. - */ - public function defaultAnswer(StubInterface $stub) - { - if ($this->state->isFull) { - $stub->returns(); - } else { - $stub->forwards(); - } - } - /** * Create a new stub verifier. * @@ -412,7 +418,7 @@ protected function createStub($name) $this ), $mock, - array($this, 'defaultAnswer') + $this->state->defaultAnswerCallback ); } elseif (isset($this->uncallableMethods[$key])) { $stub = $this->stubFactory->create( @@ -421,7 +427,7 @@ protected function createStub($name) $this ), $mock, - array($this, 'defaultAnswer') + $this->state->defaultAnswerCallback ); } elseif (isset($this->traitMethods[$key])) { $stub = $this->stubFactory->create( @@ -432,7 +438,7 @@ protected function createStub($name) $this ), $mock, - array($this, 'defaultAnswer') + $this->state->defaultAnswerCallback ); } elseif (array_key_exists($key, $this->customMethods)) { $stub = $this->stubFactory->create( @@ -443,7 +449,7 @@ protected function createStub($name) $this->invoker ), $mock, - array($this, 'defaultAnswer') + $this->state->defaultAnswerCallback ); } else { $method = $this->class->getMethod($name); @@ -458,7 +464,7 @@ protected function createStub($name) $stub = $this->stubFactory->create( new WrappedMethod($this->callParentMethod, $method, $this), $mock, - array($this, 'defaultAnswer') + $this->state->defaultAnswerCallback ); } diff --git a/src/Mock/Proxy/AbstractStaticProxy.php b/src/Mock/Proxy/AbstractStaticProxy.php index d24cc7b0e..dd917d2cd 100644 --- a/src/Mock/Proxy/AbstractStaticProxy.php +++ b/src/Mock/Proxy/AbstractStaticProxy.php @@ -45,6 +45,13 @@ public function __construct( AssertionRecorderInterface $assertionRecorder = null, InvokerInterface $invoker = null ) { + if (null === $state) { + $state = (object) array( + 'defaultAnswerCallback' => + 'Eloquent\Phony\Stub\Stub::forwardsAnswerCallback', + 'stubs' => (object) array(), + ); + } if ($class->hasMethod('_callParentStatic')) { $callParentMethod = $class->getMethod('_callParentStatic'); $callParentMethod->setAccessible(true); diff --git a/src/Mock/Proxy/Factory/ProxyFactory.php b/src/Mock/Proxy/Factory/ProxyFactory.php index e6a139f98..595ff2f89 100644 --- a/src/Mock/Proxy/Factory/ProxyFactory.php +++ b/src/Mock/Proxy/Factory/ProxyFactory.php @@ -166,24 +166,25 @@ public function createStubbing($mock, $label = null) $mock = $mock->mock(); } - if ($mock instanceof MockInterface) { - $class = new ReflectionClass($mock); + if (!$mock instanceof MockInterface) { + throw new InvalidMockException($mock); + } - $proxyProperty = $class->getProperty('_proxy'); - $proxyProperty->setAccessible(true); + $class = new ReflectionClass($mock); - if ($proxy = $proxyProperty->getValue($mock)) { - return $proxy; - } - } else { - throw new InvalidMockException($mock); + $proxyProperty = $class->getProperty('_proxy'); + $proxyProperty->setAccessible(true); + + if ($proxy = $proxyProperty->getValue($mock)) { + return $proxy; } - return new StubbingProxy( + $proxy = new StubbingProxy( $mock, (object) array( + 'defaultAnswerCallback' => + 'Eloquent\Phony\Stub\Stub::returnsNullAnswerCallback', 'stubs' => (object) array(), - 'isFull' => false, 'label' => $label, ), $this->stubFactory, @@ -192,6 +193,10 @@ public function createStubbing($mock, $label = null) $this->assertionRecorder, $this->invoker ); + + $proxyProperty->setValue($mock, $proxy); + + return $proxy; } /** @@ -260,7 +265,7 @@ public function createStubbingStatic($class) return $proxy; } - return new StaticStubbingProxy( + $proxy = new StaticStubbingProxy( $class, null, $this->stubFactory, @@ -269,6 +274,10 @@ public function createStubbingStatic($class) $this->assertionRecorder, $this->invoker ); + + $proxyProperty->setValue(null, $proxy); + + return $proxy; } /** diff --git a/src/Mock/Proxy/ProxyInterface.php b/src/Mock/Proxy/ProxyInterface.php index b6abf71b9..2e134049e 100644 --- a/src/Mock/Proxy/ProxyInterface.php +++ b/src/Mock/Proxy/ProxyInterface.php @@ -62,13 +62,24 @@ public function full(); public function partial(); /** - * Returns true if the mock is a full mock. + * Set the callback to use when creating a default answer. * * @api * - * @return boolean True if the mock is a full mock. + * @param callable $defaultAnswerCallback The default answer callback. + * + * @return $this This proxy. + */ + public function setDefaultAnswerCallback($defaultAnswerCallback); + + /** + * Get the default answer callback. + * + * @api + * + * @return callable The default answer callback. */ - public function isFull(); + public function defaultAnswerCallback(); /** * Get a stub verifier. diff --git a/src/Stub/Stub.php b/src/Stub/Stub.php index 66cb88f23..b6f9df078 100644 --- a/src/Stub/Stub.php +++ b/src/Stub/Stub.php @@ -45,6 +45,16 @@ public static function forwardsAnswerCallback(StubInterface $stub) $stub->forwards(); } + /** + * Creates a answer that returns `null` on the supplied stub. + * + * @param StubInterface $stub The stub. + */ + public static function returnsNullAnswerCallback(StubInterface $stub) + { + $stub->returns(); + } + /** * Construct a new stub. * @@ -195,6 +205,20 @@ public function self() return $this; } + /** + * Set the callback to use when creating a default answer. + * + * @param callable $defaultAnswerCallback The default answer callback. + * + * @return $this This stub. + */ + public function setDefaultAnswerCallback($defaultAnswerCallback) + { + $this->defaultAnswerCallback = $defaultAnswerCallback; + + return $this; + } + /** * Modify the current criteria to match the supplied arguments. * diff --git a/src/Stub/StubInterface.php b/src/Stub/StubInterface.php index db35ea09a..a9fe8221e 100644 --- a/src/Stub/StubInterface.php +++ b/src/Stub/StubInterface.php @@ -45,6 +45,26 @@ public function setSelf($self); */ public function self(); + /** + * Set the callback to use when creating a default answer. + * + * @api + * + * @param callable $defaultAnswerCallback The default answer callback. + * + * @return $this This stub. + */ + public function setDefaultAnswerCallback($defaultAnswerCallback); + + /** + * Get the default answer callback. + * + * @api + * + * @return callable The default answer callback. + */ + public function defaultAnswerCallback(); + /** * Modify the current criteria to match the supplied arguments. * diff --git a/src/Stub/StubVerifier.php b/src/Stub/StubVerifier.php index c7b955c64..400b5f389 100644 --- a/src/Stub/StubVerifier.php +++ b/src/Stub/StubVerifier.php @@ -123,6 +123,30 @@ public function self() return $this->stub->self(); } + /** + * Get the default answer callback. + * + * @return callable The default answer callback. + */ + public function defaultAnswerCallback() + { + return $this->stub->defaultAnswerCallback(); + } + + /** + * Set the callback to use when creating a default answer. + * + * @param callable $defaultAnswerCallback The default answer callback. + * + * @return $this This stub. + */ + public function setDefaultAnswerCallback($defaultAnswerCallback) + { + $this->stub->setDefaultAnswerCallback($defaultAnswerCallback); + + return $this; + } + /** * Set the label. * @@ -138,9 +162,9 @@ public function setLabel($label) } /** - * Get the lbel. + * Get the label. * - * @return string|null The lbel. + * @return string|null The label. */ public function label() { diff --git a/test/suite/Matcher/EqualToMatcherTest.php b/test/suite/Matcher/EqualToMatcherTest.php index 0ca9e71ce..35dce2bd5 100644 --- a/test/suite/Matcher/EqualToMatcherTest.php +++ b/test/suite/Matcher/EqualToMatcherTest.php @@ -470,11 +470,11 @@ public function testMockMatching() $className = 'PhonyMockEqualToMatcherMatchesMocks'; $builder = MockBuilderFactory::instance()->create('Eloquent\Phony\Test\Properties\TestBaseClass') ->named($className); - $mockA1 = $builder->create(); + $mockA1 = $builder->full(); Phony::on($mockA1)->setLabel('a'); - $mockA2 = $builder->create(); + $mockA2 = $builder->full(); Phony::on($mockA2)->setLabel('a'); - $mockB1 = $builder->create(); + $mockB1 = $builder->full(); Phony::on($mockB1)->setLabel('b'); $mockX1 = new $className(); diff --git a/test/suite/Mock/Builder/MockBuilderTest.php b/test/suite/Mock/Builder/MockBuilderTest.php index 48a15e46a..7f3fe583a 100644 --- a/test/suite/Mock/Builder/MockBuilderTest.php +++ b/test/suite/Mock/Builder/MockBuilderTest.php @@ -577,10 +577,10 @@ public function testGet() $this->assertSame($actual, $this->subject->get()); } - public function testCreate() + public function testPartial() { $this->setUpWith($this->typeNames); - $first = $this->subject->create('a', 'b'); + $first = $this->subject->partial('a', 'b'); $this->assertTrue($this->subject->isFinalized()); $this->assertTrue($this->subject->isBuilt()); @@ -589,17 +589,17 @@ public function testCreate() $this->assertSame(array('a', 'b'), $first->constructorArguments); $this->assertSame($first, $this->subject->get()); - $second = $this->subject->create(); + $second = $this->subject->partial(); $this->assertNotSame($first, $second); $this->assertSame(array(), $second->constructorArguments); $this->assertSame($second, $this->subject->get()); } - public function testCreateWith() + public function testPartialWith() { $this->setUpWith($this->typeNames); - $first = $this->subject->createWith(array('a', 'b')); + $first = $this->subject->partialWith(array('a', 'b')); $this->assertTrue($this->subject->isFinalized()); $this->assertTrue($this->subject->isBuilt()); @@ -608,20 +608,20 @@ public function testCreateWith() $this->assertSame(array('a', 'b'), $first->constructorArguments); $this->assertSame($first, $this->subject->get()); - $second = $this->subject->createWith(array()); + $second = $this->subject->partialWith(array()); $this->assertNotSame($first, $second); $this->assertSame(array(), $second->constructorArguments); $this->assertSame($second, $this->subject->get()); - $third = $this->subject->createWith(); + $third = $this->subject->partialWith(); $this->assertNotSame($first, $third); $this->assertNotSame($second, $third); $this->assertSame(array(), $second->constructorArguments); $this->assertSame($third, $this->subject->get()); - $third = $this->subject->createWith(null); + $third = $this->subject->partialWith(null); $this->assertNotSame($first, $third); $this->assertNotSame($second, $third); @@ -674,7 +674,7 @@ public function testMockedConstructorWithReferenceParameters() $first = null; $second = null; $builder = new MockBuilder('Eloquent\Phony\Test\TestClassA'); - $builder->createWith(array(&$first, &$second)); + $builder->partialWith(array(&$first, &$second)); $this->assertSame('first', $first); $this->assertSame('second', $second); diff --git a/test/suite/Mock/Factory/MockFactoryTest.php b/test/suite/Mock/Factory/MockFactoryTest.php index 16140b320..52e7d6303 100644 --- a/test/suite/Mock/Factory/MockFactoryTest.php +++ b/test/suite/Mock/Factory/MockFactoryTest.php @@ -97,7 +97,7 @@ public function testCreateMockClassFailureSyntax() $this->subject->createMockClass($builder); } - public function testCreateMock() + public function testCreateFullMock() { $builder = new MockBuilder( array( @@ -112,8 +112,42 @@ public function testCreateMock() ), ) ); - $builder->named(__NAMESPACE__ . '\PhonyMockFactoryTestCreateMock'); - $actual = $this->subject->createMock($builder); + $builder->named(__NAMESPACE__ . '\PhonyMockFactoryTestCreateFullMock'); + $actual = $this->subject->createFullMock($builder); + $class = new ReflectionClass($actual); + $protectedMethod = $class->getMethod('testClassAMethodC'); + $protectedMethod->setAccessible(true); + $protectedStaticMethod = $class->getMethod('testClassAStaticMethodC'); + $protectedStaticMethod->setAccessible(true); + + $this->assertInstanceOf('Eloquent\Phony\Mock\MockInterface', $actual); + $this->assertInstanceOf('Eloquent\Phony\Test\TestClassB', $actual); + $this->assertSame('0', $this->proxyFactory->createStubbing($actual)->label()); + $this->assertNull($actual->testClassAMethodA('a', 'b')); + $this->assertNull($protectedMethod->invoke($actual, 'a', 'b')); + $this->assertNull($actual->methodB('a', 'b')); + $this->assertSame('ab', PhonyMockFactoryTestCreateFullMock::testClassAStaticMethodA('a', 'b')); + $this->assertSame('protected ab', $protectedStaticMethod->invoke(null, 'a', 'b')); + $this->assertSame('static custom ab', PhonyMockFactoryTestCreateFullMock::methodA('a', 'b')); + } + + public function testCreatePartialMock() + { + $builder = new MockBuilder( + array( + 'Eloquent\Phony\Test\TestClassB', + array( + 'static methodA' => function () { + return 'static custom ' . implode(func_get_args()); + }, + 'methodB' => function () { + return 'custom ' . implode(func_get_args()); + }, + ), + ) + ); + $builder->named(__NAMESPACE__ . '\PhonyMockFactoryTestCreatePartialMock'); + $actual = $this->subject->createPartialMock($builder); $class = new ReflectionClass($actual); $protectedMethod = $class->getMethod('testClassAMethodC'); $protectedMethod->setAccessible(true); @@ -126,25 +160,25 @@ public function testCreateMock() $this->assertSame('ab', $actual->testClassAMethodA('a', 'b')); $this->assertSame('protected ab', $protectedMethod->invoke($actual, 'a', 'b')); $this->assertSame('custom ab', $actual->methodB('a', 'b')); - $this->assertSame('ab', PhonyMockFactoryTestCreateMock::testClassAStaticMethodA('a', 'b')); + $this->assertSame('ab', PhonyMockFactoryTestCreatePartialMock::testClassAStaticMethodA('a', 'b')); $this->assertSame('protected ab', $protectedStaticMethod->invoke(null, 'a', 'b')); - $this->assertSame('static custom ab', PhonyMockFactoryTestCreateMock::methodA('a', 'b')); + $this->assertSame('static custom ab', PhonyMockFactoryTestCreatePartialMock::methodA('a', 'b')); } - public function testCreateMockWithConstructorArgumentsWithReferences() + public function testCreatePartialMockWithConstructorArgumentsWithReferences() { $builder = new MockBuilder('Eloquent\Phony\Test\TestClassA'); - $builder->named(__NAMESPACE__ . '\PhonyMockFactoryTestCreateMockWithConstructorArgumentsWithReferences'); + $builder->named(__NAMESPACE__ . '\PhonyMockFactoryTestCreatePartialMockWithConstructorArgumentsWithReferences'); $a = 'a'; $b = 'b'; - $actual = $this->subject->createMock($builder, array(&$a, &$b)); + $actual = $this->subject->createPartialMock($builder, array(&$a, &$b)); $this->assertSame(array('a', 'b'), $actual->constructorArguments); $this->assertSame('first', $a); $this->assertSame('second', $b); } - public function testCreateMockWithOldConstructor() + public function testCreatePartialMockWithOldConstructor() { if (!$this->featureDetector->isSupported('object.constructor.php4')) { $this->markTestSkipped('Requires PHP4-style constructors.'); @@ -153,8 +187,8 @@ public function testCreateMockWithOldConstructor() require_once __DIR__ . '/../../../src/TestClassOldConstructor.php'; $builder = new MockBuilder('TestClassOldConstructor'); - $builder->named(__NAMESPACE__ . '\PhonyMockFactoryTestCreateMockWithOldConstructor'); - $actual = $this->subject->createMock($builder, array('a', 'b')); + $builder->named(__NAMESPACE__ . '\PhonyMockFactoryTestCreatePartialMockWithOldConstructor'); + $actual = $this->subject->createPartialMock($builder, array('a', 'b')); $this->assertSame(array('a', 'b'), $actual->constructorArguments); } diff --git a/test/suite/Mock/Method/WrappedCustomMethodTest.php b/test/suite/Mock/Method/WrappedCustomMethodTest.php index 9af8c1075..e680fff2e 100644 --- a/test/suite/Mock/Method/WrappedCustomMethodTest.php +++ b/test/suite/Mock/Method/WrappedCustomMethodTest.php @@ -26,7 +26,7 @@ protected function setUp() }; $this->method = new ReflectionMethod($this, 'setUp'); $this->mockBuilder = new MockBuilder(); - $this->mock = $this->mockBuilder->create(); + $this->mock = $this->mockBuilder->partial(); $this->proxyFactory = new ProxyFactory(); $this->proxy = $this->proxyFactory->createStubbing($this->mock); $this->invoker = new Invoker(); diff --git a/test/suite/Mock/Method/WrappedMagicMethodTest.php b/test/suite/Mock/Method/WrappedMagicMethodTest.php index 3cb229424..66bbbceb1 100644 --- a/test/suite/Mock/Method/WrappedMagicMethodTest.php +++ b/test/suite/Mock/Method/WrappedMagicMethodTest.php @@ -24,7 +24,7 @@ protected function setUp() $this->callMagicMethod = new ReflectionMethod($this, 'setUp'); $this->isUncallable = false; $this->mockBuilder = new MockBuilder(); - $this->mock = $this->mockBuilder->create(); + $this->mock = $this->mockBuilder->partial(); $this->proxyFactory = new ProxyFactory(); $this->proxy = $this->proxyFactory->createStubbing($this->mock); $this->subject = new WrappedMagicMethod($this->name, $this->callMagicMethod, $this->isUncallable, $this->proxy); diff --git a/test/suite/Mock/Method/WrappedMethodTest.php b/test/suite/Mock/Method/WrappedMethodTest.php index 3f91cf6d9..08b83f3ad 100644 --- a/test/suite/Mock/Method/WrappedMethodTest.php +++ b/test/suite/Mock/Method/WrappedMethodTest.php @@ -23,7 +23,7 @@ protected function setUp() $this->callParentMethod = new ReflectionMethod($this, 'setUp'); $this->method = new ReflectionMethod('Eloquent\Phony\Test\TestClassA::testClassAMethodE'); $this->mockBuilder = new MockBuilder(); - $this->mock = $this->mockBuilder->create(); + $this->mock = $this->mockBuilder->partial(); $this->proxyFactory = new ProxyFactory(); $this->proxy = $this->proxyFactory->createStubbing($this->mock); $this->subject = new WrappedMethod($this->callParentMethod, $this->method, $this->proxy); diff --git a/test/suite/Mock/Method/WrappedTraitMethodTest.php b/test/suite/Mock/Method/WrappedTraitMethodTest.php index 0c6d1386c..7da266b7e 100644 --- a/test/suite/Mock/Method/WrappedTraitMethodTest.php +++ b/test/suite/Mock/Method/WrappedTraitMethodTest.php @@ -31,7 +31,7 @@ protected function setUp() $this->traitName = 'Eloquent\Phony\Test\TestTraitA'; $this->method = new ReflectionMethod('Eloquent\Phony\Test\TestTraitA::testClassAMethodB'); $this->mockBuilder = new MockBuilder(); - $this->mock = $this->mockBuilder->create(); + $this->mock = $this->mockBuilder->partial(); $this->proxyFactory = new ProxyFactory(); $this->proxy = $this->proxyFactory->createStubbing($this->mock); $this->subject = new WrappedTraitMethod($this->callTraitMethod, $this->traitName, $this->method, $this->proxy); diff --git a/test/suite/Mock/Method/WrappedUncallableMethodTest.php b/test/suite/Mock/Method/WrappedUncallableMethodTest.php index ce78cc43b..a580f9735 100644 --- a/test/suite/Mock/Method/WrappedUncallableMethodTest.php +++ b/test/suite/Mock/Method/WrappedUncallableMethodTest.php @@ -22,7 +22,7 @@ protected function setUp() { $this->method = new ReflectionMethod('Eloquent\Phony\Test\TestClassA::testClassAMethodA'); $this->mockBuilder = new MockBuilder(); - $this->mock = $this->mockBuilder->create(); + $this->mock = $this->mockBuilder->partial(); $this->proxyFactory = new ProxyFactory(); $this->proxy = $this->proxyFactory->createStubbing($this->mock); $this->subject = new WrappedUncallableMethod($this->method, $this->proxy); diff --git a/test/suite/Mock/Proxy/Factory/ProxyFactoryTest.php b/test/suite/Mock/Proxy/Factory/ProxyFactoryTest.php index d02dede64..c6d88b781 100644 --- a/test/suite/Mock/Proxy/Factory/ProxyFactoryTest.php +++ b/test/suite/Mock/Proxy/Factory/ProxyFactoryTest.php @@ -64,15 +64,15 @@ public function testConstructorDefaults() public function testCreateStubbingNew() { $mockBuilder = new MockBuilder('Eloquent\Phony\Test\TestClassB'); - $mock = $mockBuilder->create(); + $mock = $mockBuilder->full(); $proxyProperty = new ReflectionProperty($mock, '_proxy'); $proxyProperty->setAccessible(true); $proxyProperty->setValue($mock, null); $expected = new StubbingProxy( $mock, (object) array( + 'defaultAnswerCallback' => 'Eloquent\Phony\Stub\Stub::returnsNullAnswerCallback', 'stubs' => (object) array(), - 'isFull' => false, 'label' => 'label', ), $this->stubFactory, @@ -89,7 +89,7 @@ public function testCreateStubbingNew() public function testCreateStubbingAdapt() { $mockBuilder = new MockBuilder('Eloquent\Phony\Test\TestClassB'); - $mock = $mockBuilder->create(); + $mock = $mockBuilder->full(); $proxyProperty = new ReflectionProperty($mock, '_proxy'); $proxyProperty->setAccessible(true); $expected = $proxyProperty->getValue($mock); @@ -102,7 +102,7 @@ public function testCreateStubbingAdapt() public function testCreateStubbingFromVerifier() { $mockBuilder = new MockBuilder('Eloquent\Phony\Test\TestClassB'); - $mock = $mockBuilder->create(); + $mock = $mockBuilder->full(); $proxyProperty = new ReflectionProperty($mock, '_proxy'); $proxyProperty->setAccessible(true); $expected = $proxyProperty->getValue($mock); @@ -121,7 +121,7 @@ public function testCreateStubbingFailureInvalid() public function testCreateVerification() { $mockBuilder = new MockBuilder('Eloquent\Phony\Test\TestClassB'); - $mock = $mockBuilder->create(); + $mock = $mockBuilder->full(); $proxyProperty = new ReflectionProperty($mock, '_proxy'); $proxyProperty->setAccessible(true); $stubbingProxy = $proxyProperty->getValue($mock); @@ -130,14 +130,13 @@ public function testCreateVerification() $this->assertInstanceOf('Eloquent\Phony\Mock\Proxy\Verification\VerificationProxy', $actual); $this->assertSame($stubbingProxy->mock(), $actual->mock()); $this->assertSame($stubbingProxy->stubs(), $actual->stubs()); - $this->assertSame($stubbingProxy->isFull(), $actual->isFull()); $this->assertSame($stubbingProxy->label(), $actual->label()); } public function testCreateVerificationAdapt() { $mockBuilder = new MockBuilder('Eloquent\Phony\Test\TestClassB'); - $mock = $mockBuilder->create(); + $mock = $mockBuilder->full(); $actual = $this->subject->createVerification($mock); $this->assertSame($actual, $this->subject->createVerification($actual)); @@ -146,14 +145,13 @@ public function testCreateVerificationAdapt() public function testCreateVerificationFromStubbing() { $mockBuilder = new MockBuilder('Eloquent\Phony\Test\TestClassB'); - $mock = $mockBuilder->create(); + $mock = $mockBuilder->full(); $stubbingProxy = $this->subject->createStubbing($mock); $actual = $this->subject->createVerification($mock); $this->assertInstanceOf('Eloquent\Phony\Mock\Proxy\Verification\VerificationProxy', $actual); $this->assertSame($stubbingProxy->mock(), $actual->mock()); $this->assertSame($stubbingProxy->stubs(), $actual->stubs()); - $this->assertSame($stubbingProxy->isFull(), $actual->isFull()); $this->assertSame($stubbingProxy->label(), $actual->label()); } @@ -211,7 +209,7 @@ public function testCreateStubbingStaticFromMock() $proxyProperty = $class->getProperty('_staticProxy'); $proxyProperty->setAccessible(true); $expected = $proxyProperty->getValue(null); - $actual = $this->subject->createStubbingStatic($mockBuilder->create()); + $actual = $this->subject->createStubbingStatic($mockBuilder->partial()); $this->assertSame($expected, $actual); } @@ -264,7 +262,6 @@ public function testCreateVerificationStatic() $this->assertInstanceOf('Eloquent\Phony\Mock\Proxy\Verification\StaticVerificationProxy', $actual); $this->assertSame($stubbingProxy->clazz(), $actual->clazz()); $this->assertSame($stubbingProxy->stubs(), $actual->stubs()); - $this->assertSame($stubbingProxy->isFull(), $actual->isFull()); } public function testCreateVerificationStaticAdapt() @@ -286,7 +283,6 @@ public function testCreateVerificationStaticFromStubbing() $this->assertInstanceOf('Eloquent\Phony\Mock\Proxy\Verification\StaticVerificationProxy', $actual); $this->assertSame($stubbingProxy->clazz(), $actual->clazz()); $this->assertSame($stubbingProxy->stubs(), $actual->stubs()); - $this->assertSame($stubbingProxy->isFull(), $actual->isFull()); } public function testInstance() diff --git a/test/suite/Mock/Proxy/Stubbing/StaticStubbingProxyTest.php b/test/suite/Mock/Proxy/Stubbing/StaticStubbingProxyTest.php index b6758112c..a31745a0a 100644 --- a/test/suite/Mock/Proxy/Stubbing/StaticStubbingProxyTest.php +++ b/test/suite/Mock/Proxy/Stubbing/StaticStubbingProxyTest.php @@ -25,7 +25,10 @@ class StaticStubbingProxyTest extends PHPUnit_Framework_TestCase { protected function setUp() { - $this->state = (object) array('stubs' => (object) array(), 'isFull' => true); + $this->state = (object) array( + 'stubs' => (object) array(), + 'defaultAnswerCallback' => 'Eloquent\Phony\Stub\Stub::returnsNullAnswerCallback', + ); $this->stubFactory = new StubFactory(); $this->stubVerifierFactory = new StubVerifierFactory(); $this->assertionRenderer = new AssertionRenderer(); @@ -64,7 +67,6 @@ public function testConstructor() $this->assertSame($this->class, $this->subject->clazz()); $this->assertSame($this->className, $this->subject->className()); $this->assertSame($this->state->stubs, $this->subject->stubs()); - $this->assertSame($this->state->isFull, $this->subject->isFull()); $this->assertSame($this->state, $this->subject->state()); $this->assertSame($this->stubFactory, $this->subject->stubFactory()); $this->assertSame($this->stubVerifierFactory, $this->subject->stubVerifierFactory()); @@ -80,7 +82,6 @@ public function testConstructorDefaults() $this->subject = new StaticStubbingProxy($this->class); $this->assertEquals((object) array(), $this->subject->stubs()); - $this->assertFalse($this->subject->isFull()); $this->assertSame(StubFactory::instance(), $this->subject->stubFactory()); $this->assertSame(StubVerifierFactory::instance(), $this->subject->stubVerifierFactory()); $this->assertSame(AssertionRenderer::instance(), $this->subject->assertionRenderer()); @@ -94,7 +95,6 @@ public function testFull() $className = $this->className; $this->assertSame($this->subject, $this->subject->full()); - $this->assertTrue($this->subject->isFull()); $this->assertNull($className::testClassAStaticMethodA()); $this->assertNull($className::testClassAStaticMethodB('a', 'b')); } @@ -105,11 +105,22 @@ public function testPartial() $className = $this->className; $this->assertSame($this->subject, $this->subject->partial()); - $this->assertFalse($this->subject->isFull()); $this->assertSame('', $className::testClassAStaticMethodA()); $this->assertSame('ab', $className::testClassAStaticMethodB('a', 'b')); } + public function testSetDefaultAnswerCallback() + { + $this->setUpWith('Eloquent\Phony\Test\TestClassA'); + $callbackA = function () {}; + $callbackB = function () {}; + + $this->assertSame($this->subject, $this->subject->setDefaultAnswerCallback($callbackA)); + $this->assertSame($callbackA, $this->subject->defaultAnswerCallback()); + $this->assertSame($this->subject, $this->subject->setDefaultAnswerCallback($callbackB)); + $this->assertSame($callbackB, $this->subject->defaultAnswerCallback()); + } + public function testStub() { $this->setUpWith('Eloquent\Phony\Test\TestClassA'); diff --git a/test/suite/Mock/Proxy/Stubbing/StubbingProxyTest.php b/test/suite/Mock/Proxy/Stubbing/StubbingProxyTest.php index 5806822b3..b83b008d5 100644 --- a/test/suite/Mock/Proxy/Stubbing/StubbingProxyTest.php +++ b/test/suite/Mock/Proxy/Stubbing/StubbingProxyTest.php @@ -25,7 +25,11 @@ class StubbingProxyTest extends PHPUnit_Framework_TestCase { protected function setUp() { - $this->state = (object) array('stubs' => (object) array(), 'isFull' => true, 'label' => 'label'); + $this->state = (object) array( + 'stubs' => (object) array(), + 'defaultAnswerCallback' => 'Eloquent\Phony\Stub\Stub::returnsNullAnswerCallback', + 'label' => 'label', + ); $this->stubFactory = new StubFactory(); $this->stubVerifierFactory = new StubVerifierFactory(); $this->assertionRenderer = new AssertionRenderer(); @@ -40,7 +44,7 @@ protected function setUpWith($className, $mockClassName = null) $this->mockBuilder = new MockBuilder($className); $this->mockBuilder->named($mockClassName); $this->class = $this->mockBuilder->build(true); - $this->mock = $this->mockBuilder->create(); + $this->mock = $this->mockBuilder->partial(); $this->subject = new StubbingProxy( $this->mock, $this->state, @@ -67,7 +71,6 @@ public function testConstructor() $this->assertSame($this->className, $this->subject->clazz()->getName()); $this->assertSame($this->className, $this->subject->className()); $this->assertSame($this->state->stubs, $this->subject->stubs()); - $this->assertSame($this->state->isFull, $this->subject->isFull()); $this->assertSame($this->state->label, $this->subject->label()); $this->assertTrue($this->subject->isAdaptable()); $this->assertSame($this->stubFactory, $this->subject->stubFactory()); @@ -81,11 +84,10 @@ public function testConstructorDefaults() { $this->mockBuilder = new MockBuilder('Eloquent\Phony\Test\TestClassB'); $this->class = $this->mockBuilder->build(true); - $this->mock = $this->mockBuilder->create(); + $this->mock = $this->mockBuilder->partial(); $this->subject = new StubbingProxy($this->mock); $this->assertEquals((object) array(), $this->subject->stubs()); - $this->assertFalse($this->subject->isFull()); $this->assertSame(StubFactory::instance(), $this->subject->stubFactory()); $this->assertSame(StubVerifierFactory::instance(), $this->subject->stubVerifierFactory()); $this->assertSame(AssertionRenderer::instance(), $this->subject->assertionRenderer()); @@ -117,7 +119,6 @@ public function testFull() $this->setUpWith('Eloquent\Phony\Test\TestClassB'); $this->assertSame($this->subject, $this->subject->full()); - $this->assertTrue($this->subject->isFull()); $this->assertNull($this->mock->testClassAMethodA()); $this->assertNull($this->mock->testClassAMethodB('a', 'b')); } @@ -127,11 +128,22 @@ public function testPartial() $this->setUpWith('Eloquent\Phony\Test\TestClassB'); $this->assertSame($this->subject, $this->subject->partial()); - $this->assertFalse($this->subject->isFull()); $this->assertSame('', $this->mock->testClassAMethodA()); $this->assertSame('ab', $this->mock->testClassAMethodB('a', 'b')); } + public function testSetDefaultAnswerCallback() + { + $this->setUpWith('Eloquent\Phony\Test\TestClassA'); + $callbackA = function () {}; + $callbackB = function () {}; + + $this->assertSame($this->subject, $this->subject->setDefaultAnswerCallback($callbackA)); + $this->assertSame($callbackA, $this->subject->defaultAnswerCallback()); + $this->assertSame($this->subject, $this->subject->setDefaultAnswerCallback($callbackB)); + $this->assertSame($callbackB, $this->subject->defaultAnswerCallback()); + } + public function testStub() { $this->setUpWith('Eloquent\Phony\Test\TestClassA'); @@ -257,7 +269,7 @@ public function testConstruct() { $this->mockBuilder = new MockBuilder('Eloquent\Phony\Test\TestClassB'); $this->class = $this->mockBuilder->build(true); - $this->mock = $this->mockBuilder->createWith(null); + $this->mock = $this->mockBuilder->partialWith(null); $this->subject = new StubbingProxy($this->mock); $this->assertNull($this->mock->constructorArguments); @@ -269,7 +281,7 @@ public function testConstructWith() { $this->mockBuilder = new MockBuilder('Eloquent\Phony\Test\TestClassB'); $this->class = $this->mockBuilder->build(true); - $this->mock = $this->mockBuilder->createWith(null); + $this->mock = $this->mockBuilder->partialWith(null); $this->subject = new StubbingProxy($this->mock); $this->assertNull($this->mock->constructorArguments); @@ -281,7 +293,7 @@ public function testConstructWithWithReferenceParameters() { $this->mockBuilder = new MockBuilder('Eloquent\Phony\Test\TestClassA'); $this->class = $this->mockBuilder->build(true); - $this->mock = $this->mockBuilder->createWith(null); + $this->mock = $this->mockBuilder->partialWith(null); $this->subject = new StubbingProxy($this->mock); $a = 'a'; $b = 'b'; @@ -369,11 +381,12 @@ public function testStubbingWithCustomMethod() ) ); $this->class = $this->mockBuilder->build(true); - $this->mock = $this->mockBuilder->create(); + $this->mock = $this->mockBuilder->partial(); $this->subject = new StubbingProxy($this->mock); $proxyProperty = $this->class->getProperty('_proxy'); $proxyProperty->setAccessible(true); $proxyProperty->setValue($this->mock, $this->subject); + $this->subject->partial(); $this->subject->methodA('a', 'b')->returns('x'); $this->assertSame('x', $this->mock->methodA('a', 'b')); diff --git a/test/suite/Mock/Proxy/Verification/StaticVerificationProxyTest.php b/test/suite/Mock/Proxy/Verification/StaticVerificationProxyTest.php index c1f0bc954..5e45433cd 100644 --- a/test/suite/Mock/Proxy/Verification/StaticVerificationProxyTest.php +++ b/test/suite/Mock/Proxy/Verification/StaticVerificationProxyTest.php @@ -26,7 +26,10 @@ class StaticVerificationProxyTest extends PHPUnit_Framework_TestCase { protected function setUp() { - $this->state = (object) array('stubs' => (object) array(), 'isFull' => true); + $this->state = (object) array( + 'stubs' => (object) array(), + 'defaultAnswerCallback' => 'Eloquent\Phony\Stub\Stub::returnsNullAnswerCallback', + ); $this->stubFactory = new StubFactory(); $this->stubVerifierFactory = new StubVerifierFactory(); $this->assertionRenderer = new AssertionRenderer(); @@ -69,7 +72,6 @@ public function testConstructor() $this->assertSame($this->class, $this->subject->clazz()); $this->assertSame($this->className, $this->subject->className()); $this->assertSame($this->state->stubs, $this->subject->stubs()); - $this->assertSame($this->state->isFull, $this->subject->isFull()); $this->assertSame($this->stubFactory, $this->subject->stubFactory()); $this->assertSame($this->stubVerifierFactory, $this->subject->stubVerifierFactory()); $this->assertSame($this->assertionRenderer, $this->subject->assertionRenderer()); @@ -84,7 +86,6 @@ public function testConstructorDefaults() $this->subject = new StaticVerificationProxy($this->class); $this->assertEquals((object) array(), $this->subject->stubs()); - $this->assertFalse($this->subject->isFull()); $this->assertSame(StubFactory::instance(), $this->subject->stubFactory()); $this->assertSame(StubVerifierFactory::instance(), $this->subject->stubVerifierFactory()); $this->assertSame(AssertionRenderer::instance(), $this->subject->assertionRenderer()); @@ -98,7 +99,6 @@ public function testFull() $className = $this->className; $this->assertSame($this->subject, $this->subject->full()); - $this->assertTrue($this->subject->isFull()); $this->assertNull($className::testClassAStaticMethodA()); $this->assertNull($className::testClassAStaticMethodB('a', 'b')); } @@ -109,11 +109,22 @@ public function testPartial() $className = $this->className; $this->assertSame($this->subject, $this->subject->partial()); - $this->assertFalse($this->subject->isFull()); $this->assertSame('', $className::testClassAStaticMethodA()); $this->assertSame('ab', $className::testClassAStaticMethodB('a', 'b')); } + public function testSetDefaultAnswerCallback() + { + $this->setUpWith('Eloquent\Phony\Test\TestClassA'); + $callbackA = function () {}; + $callbackB = function () {}; + + $this->assertSame($this->subject, $this->subject->setDefaultAnswerCallback($callbackA)); + $this->assertSame($callbackA, $this->subject->defaultAnswerCallback()); + $this->assertSame($this->subject, $this->subject->setDefaultAnswerCallback($callbackB)); + $this->assertSame($callbackB, $this->subject->defaultAnswerCallback()); + } + public function testStub() { $this->setUpWith('Eloquent\Phony\Test\TestClassA'); diff --git a/test/suite/Mock/Proxy/Verification/VerificationProxyTest.php b/test/suite/Mock/Proxy/Verification/VerificationProxyTest.php index dc567926f..d3ced846e 100644 --- a/test/suite/Mock/Proxy/Verification/VerificationProxyTest.php +++ b/test/suite/Mock/Proxy/Verification/VerificationProxyTest.php @@ -26,7 +26,11 @@ class VerificationProxyTest extends PHPUnit_Framework_TestCase { protected function setUp() { - $this->state = (object) array('stubs' => (object) array(), 'isFull' => true, 'label' => 'label'); + $this->state = (object) array( + 'stubs' => (object) array(), + 'defaultAnswerCallback' => 'Eloquent\Phony\Stub\Stub::returnsNullAnswerCallback', + 'label' => 'label', + ); $this->isFull = true; $this->stubFactory = new StubFactory(); $this->stubVerifierFactory = new StubVerifierFactory(); @@ -42,7 +46,7 @@ protected function setUpWith($className, $mockClassName = null) $this->mockBuilder = new MockBuilder($className); $this->mockBuilder->named($mockClassName); $this->class = $this->mockBuilder->build(true); - $this->mock = $this->mockBuilder->create(); + $this->mock = $this->mockBuilder->partial(); $this->subject = new VerificationProxy( $this->mock, $this->state, @@ -73,7 +77,6 @@ public function testConstructor() $this->assertSame($this->className, $this->subject->clazz()->getName()); $this->assertSame($this->className, $this->subject->className()); $this->assertSame($this->state->stubs, $this->subject->stubs()); - $this->assertSame($this->state->isFull, $this->subject->isFull()); $this->assertSame($this->state->label, $this->subject->label()); $this->assertTrue($this->subject->isAdaptable()); $this->assertSame($this->stubFactory, $this->subject->stubFactory()); @@ -87,11 +90,10 @@ public function testConstructorDefaults() { $this->mockBuilder = new MockBuilder('Eloquent\Phony\Test\TestClassB'); $this->class = $this->mockBuilder->build(true); - $this->mock = $this->mockBuilder->create(); + $this->mock = $this->mockBuilder->partial(); $this->subject = new VerificationProxy($this->mock); $this->assertEquals((object) array(), $this->subject->stubs()); - $this->assertFalse($this->subject->isFull()); $this->assertSame(StubFactory::instance(), $this->subject->stubFactory()); $this->assertSame(StubVerifierFactory::instance(), $this->subject->stubVerifierFactory()); $this->assertSame(AssertionRenderer::instance(), $this->subject->assertionRenderer()); @@ -123,7 +125,6 @@ public function testFull() $this->setUpWith('Eloquent\Phony\Test\TestClassB'); $this->assertSame($this->subject, $this->subject->full()); - $this->assertTrue($this->subject->isFull()); $this->assertNull($this->mock->testClassAMethodA()); $this->assertNull($this->mock->testClassAMethodB('a', 'b')); } @@ -133,11 +134,22 @@ public function testPartial() $this->setUpWith('Eloquent\Phony\Test\TestClassB'); $this->assertSame($this->subject, $this->subject->partial()); - $this->assertFalse($this->subject->isFull()); $this->assertSame('', $this->mock->testClassAMethodA()); $this->assertSame('ab', $this->mock->testClassAMethodB('a', 'b')); } + public function testSetDefaultAnswerCallback() + { + $this->setUpWith('Eloquent\Phony\Test\TestClassA'); + $callbackA = function () {}; + $callbackB = function () {}; + + $this->assertSame($this->subject, $this->subject->setDefaultAnswerCallback($callbackA)); + $this->assertSame($callbackA, $this->subject->defaultAnswerCallback()); + $this->assertSame($this->subject, $this->subject->setDefaultAnswerCallback($callbackB)); + $this->assertSame($callbackB, $this->subject->defaultAnswerCallback()); + } + public function testStub() { $this->setUpWith('Eloquent\Phony\Test\TestClassA'); @@ -259,7 +271,7 @@ public function testConstruct() { $this->mockBuilder = new MockBuilder('Eloquent\Phony\Test\TestClassB'); $this->class = $this->mockBuilder->build(true); - $this->mock = $this->mockBuilder->createWith(null); + $this->mock = $this->mockBuilder->partialWith(null); $this->subject = new VerificationProxy($this->mock); $this->assertNull($this->mock->constructorArguments); @@ -271,7 +283,7 @@ public function testConstructWith() { $this->mockBuilder = new MockBuilder('Eloquent\Phony\Test\TestClassB'); $this->class = $this->mockBuilder->build(true); - $this->mock = $this->mockBuilder->createWith(null); + $this->mock = $this->mockBuilder->partialWith(null); $this->subject = new VerificationProxy($this->mock); $this->assertNull($this->mock->constructorArguments); @@ -283,7 +295,7 @@ public function testConstructWithWithReferenceParameters() { $this->mockBuilder = new MockBuilder('Eloquent\Phony\Test\TestClassA'); $this->class = $this->mockBuilder->build(true); - $this->mock = $this->mockBuilder->createWith(null); + $this->mock = $this->mockBuilder->partialWith(null); $this->subject = new VerificationProxy($this->mock); $a = 'a'; $b = 'b'; @@ -381,7 +393,7 @@ public function testVerificationWithCustomMethod() ) ); $this->class = $this->mockBuilder->build(true); - $this->mock = $this->mockBuilder->create(); + $this->mock = $this->mockBuilder->partial(); $this->subject = new VerificationProxy($this->mock); $proxyProperty = $this->class->getProperty('_staticProxy'); $proxyProperty->setAccessible(true); diff --git a/test/suite/Pho/PhonyTest.php b/test/suite/Pho/PhonyTest.php index 1db3b4b1b..f4de92b0e 100644 --- a/test/suite/Pho/PhonyTest.php +++ b/test/suite/Pho/PhonyTest.php @@ -205,7 +205,7 @@ public function testOnStaticFunction() public function testOn() { - $mock = Phony::mockBuilder()->create(); + $mock = Phony::mockBuilder()->partial(); $actual = Phony::on($mock); $this->assertInstanceOf('Eloquent\Phony\Mock\Proxy\Stubbing\StubbingProxy', $actual); @@ -214,7 +214,7 @@ public function testOn() public function testOnFunction() { - $mock = mockBuilder()->create(); + $mock = mockBuilder()->partial(); $actual = on($mock); $expected = $this->proxyFactory->createStubbing($mock); @@ -244,7 +244,7 @@ public function testVerifyStaticFunction() public function testVerify() { - $mock = Phony::mockBuilder()->create(); + $mock = Phony::mockBuilder()->partial(); $actual = Phony::verify($mock); $expected = $this->proxyFactory->createVerification($mock); @@ -254,7 +254,7 @@ public function testVerify() public function testVerifyFunction() { - $mock = mockBuilder()->create(); + $mock = mockBuilder()->partial(); $actual = verify($mock); $expected = $this->proxyFactory->createVerification($mock); diff --git a/test/suite/PhonyTest.php b/test/suite/PhonyTest.php index 2d5e9dbdd..bdeb7e013 100644 --- a/test/suite/PhonyTest.php +++ b/test/suite/PhonyTest.php @@ -192,7 +192,7 @@ public function testOnStaticFunction() public function testOn() { - $mock = Phony::mockBuilder()->create(); + $mock = Phony::mockBuilder()->partial(); $actual = Phony::on($mock); $this->assertInstanceOf('Eloquent\Phony\Mock\Proxy\Stubbing\StubbingProxy', $actual); @@ -201,7 +201,7 @@ public function testOn() public function testOnFunction() { - $mock = mockBuilder()->create(); + $mock = mockBuilder()->partial(); $actual = on($mock); $expected = $this->proxyFactory->createStubbing($mock); @@ -231,7 +231,7 @@ public function testVerifyStaticFunction() public function testVerify() { - $mock = Phony::mockBuilder()->create(); + $mock = Phony::mockBuilder()->partial(); $actual = Phony::verify($mock); $expected = $this->proxyFactory->createVerification($mock); @@ -241,7 +241,7 @@ public function testVerify() public function testVerifyFunction() { - $mock = mockBuilder()->create(); + $mock = mockBuilder()->partial(); $actual = verify($mock); $expected = $this->proxyFactory->createVerification($mock); diff --git a/test/suite/Phpunit/PhonyTest.php b/test/suite/Phpunit/PhonyTest.php index c9c432cf0..0491dd3a6 100644 --- a/test/suite/Phpunit/PhonyTest.php +++ b/test/suite/Phpunit/PhonyTest.php @@ -205,7 +205,7 @@ public function testOnStaticFunction() public function testOn() { - $mock = Phony::mockBuilder()->create(); + $mock = Phony::mockBuilder()->partial(); $actual = Phony::on($mock); $this->assertInstanceOf('Eloquent\Phony\Mock\Proxy\Stubbing\StubbingProxy', $actual); @@ -214,7 +214,7 @@ public function testOn() public function testOnFunction() { - $mock = mockBuilder()->create(); + $mock = mockBuilder()->partial(); $actual = on($mock); $expected = $this->proxyFactory->createStubbing($mock); @@ -244,7 +244,7 @@ public function testVerifyStaticFunction() public function testVerify() { - $mock = Phony::mockBuilder()->create(); + $mock = Phony::mockBuilder()->partial(); $actual = Phony::verify($mock); $expected = $this->proxyFactory->createVerification($mock); @@ -254,7 +254,7 @@ public function testVerify() public function testVerifyFunction() { - $mock = mockBuilder()->create(); + $mock = mockBuilder()->partial(); $actual = verify($mock); $expected = $this->proxyFactory->createVerification($mock); diff --git a/test/suite/Simpletest/PhonyTest.php b/test/suite/Simpletest/PhonyTest.php index b033a4437..46282c201 100644 --- a/test/suite/Simpletest/PhonyTest.php +++ b/test/suite/Simpletest/PhonyTest.php @@ -224,7 +224,7 @@ public function testOnStaticFunction() public function testOn() { - $mock = Phony::mockBuilder()->create(); + $mock = Phony::mockBuilder()->partial(); $actual = Phony::on($mock); $this->assertInstanceOf('Eloquent\Phony\Mock\Proxy\Stubbing\StubbingProxy', $actual); @@ -233,7 +233,7 @@ public function testOn() public function testOnFunction() { - $mock = mockBuilder()->create(); + $mock = mockBuilder()->partial(); $actual = on($mock); $expected = $this->proxyFactory->createStubbing($mock); @@ -263,7 +263,7 @@ public function testVerifyStaticFunction() public function testVerify() { - $mock = Phony::mockBuilder()->create(); + $mock = Phony::mockBuilder()->partial(); $actual = Phony::verify($mock); $expected = $this->proxyFactory->createVerification($mock); @@ -273,7 +273,7 @@ public function testVerify() public function testVerifyFunction() { - $mock = mockBuilder()->create(); + $mock = mockBuilder()->partial(); $actual = verify($mock); $expected = $this->proxyFactory->createVerification($mock); diff --git a/test/suite/Stub/StubTest.php b/test/suite/Stub/StubTest.php index 6a4fadffc..59a9e86a8 100644 --- a/test/suite/Stub/StubTest.php +++ b/test/suite/Stub/StubTest.php @@ -177,6 +177,17 @@ public function testSetSelf() $this->assertSame($this->self, $this->subject->self()); } + public function testSetDefaultAnswerCallback() + { + $callbackA = function () {}; + $callbackB = function () {}; + + $this->assertSame($this->subject, $this->subject->setDefaultAnswerCallback($callbackA)); + $this->assertSame($callbackA, $this->subject->defaultAnswerCallback()); + $this->assertSame($this->subject, $this->subject->setDefaultAnswerCallback($callbackB)); + $this->assertSame($callbackB, $this->subject->defaultAnswerCallback()); + } + public function testSetLabel() { $this->assertSame($this->subject, $this->subject->setLabel(null)); diff --git a/test/suite/Stub/StubVerifierTest.php b/test/suite/Stub/StubVerifierTest.php index c75fc83ae..e4f326318 100644 --- a/test/suite/Stub/StubVerifierTest.php +++ b/test/suite/Stub/StubVerifierTest.php @@ -190,6 +190,17 @@ public function testSetSelf() $this->assertSame($this->self, $this->subject->self()); } + public function testSetDefaultAnswerCallback() + { + $callbackA = function () {}; + $callbackB = function () {}; + + $this->assertSame($this->subject, $this->subject->setDefaultAnswerCallback($callbackA)); + $this->assertSame($callbackA, $this->subject->defaultAnswerCallback()); + $this->assertSame($this->subject, $this->subject->setDefaultAnswerCallback($callbackB)); + $this->assertSame($callbackB, $this->subject->defaultAnswerCallback()); + } + public function testSetLabel() { $this->assertSame($this->subject, $this->subject->setLabel(null));