Skip to content
This repository has been archived by the owner on Jul 8, 2023. It is now read-only.

Commit

Permalink
Mock default answer refactor. Closes #90, #103.
Browse files Browse the repository at this point in the history
  • Loading branch information
ezzatron committed Feb 2, 2016
1 parent c29fec2 commit cb25bb3
Show file tree
Hide file tree
Showing 33 changed files with 514 additions and 209 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
149 changes: 112 additions & 37 deletions doc/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
- [Multiple answers]
- [Overriding rules]
- [The default rule and answer]
- [The default answer callback]
- [Matching stub arguments]
- [Returning values]
- [Returning arguments]
Expand Down Expand Up @@ -531,6 +532,24 @@ Turn the mock into a [full mock].
Turn the mock into a [partial mock].

<a name="handle.defaultAnswerCallback" />

----

> *callable* $handle->[**defaultAnswerCallback**](#handle.defaultAnswerCallback)()
Get the [default answer callback].

<a name="handle.setDefaultAnswerCallback" />

----

> *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.*

<a name="handle.reset" />

----
Expand Down Expand Up @@ -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].*

<a name="builder.create" />
<a name="builder.full" />

----

> *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].*

<a name="builder.createWith" />
<a name="builder.partial" />

----

> *mock* $builder->[**createWith**](#builder.createWith)($arguments = [], $label = null)
> *mock* $builder->[**partial**](#builder.partial)(...$arguments)
Create a new [partial mock].

Expand All @@ -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].*

<a name="builder.full" />
<a name="builder.partialWith" />

----

> *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
Expand Down Expand Up @@ -1343,51 +1365,51 @@ 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
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
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -1515,6 +1540,24 @@ Get the [self value] of this stub.
Set the [self value] of this stub.

<a name="stub.defaultAnswerCallback" />

----

> *callable* $stub->[**defaultAnswerCallback**](#stub.defaultAnswerCallback)()
Get the [default answer callback].

<a name="stub.setDefaultAnswerCallback" />

----

> *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.*

<a name="stub.with" />

----
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion src/Mock/Builder/Factory/MockBuilderFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Loading

0 comments on commit cb25bb3

Please sign in to comment.