Skip to content

Commit

Permalink
Add onlyMethods, addMethods + deprecate setMethods
Browse files Browse the repository at this point in the history
  • Loading branch information
DFoxinator committed May 15, 2019
1 parent 6421ecc commit a58c6d9
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 10 deletions.
2 changes: 1 addition & 1 deletion .psalm/baseline.xml
Expand Up @@ -201,7 +201,7 @@
<PossiblyNullPropertyAssignmentValue occurrences="1">
<code>null</code>
</PossiblyNullPropertyAssignmentValue>
<ArgumentTypeCoercion occurrences="1">
<ArgumentTypeCoercion occurrences="2">
<code>$this->type</code>
</ArgumentTypeCoercion>
</file>
Expand Down
34 changes: 32 additions & 2 deletions src/Framework/MockObject/MockBuilder.php
Expand Up @@ -170,6 +170,8 @@ public function getMockForTrait(): MockObject

/**
* Specifies the subset of methods to mock. Default is to mock none of them.
*
* @deprecated https://github.com/sebastianbergmann/phpunit/pull/3687
*/
public function setMethods(array $methods = null): self
{
Expand All @@ -185,15 +187,43 @@ public function setMethods(array $methods = null): self
*
* @throws RuntimeException
*/
public function setRealMethods(array $methods): self
public function onlyMethods(array $methods): self
{
$reflection = new \ReflectionClass($this->type);

foreach ($methods as $method) {
if (!$reflection->hasMethod($method)) {
throw new RuntimeException(
\sprintf(
'Trying to set mock method "%s", but it does not exist in class "%s"',
'Trying to set mock method "%s" with onlyMethods, but it does not exist in class "%s". Use addMethods() for methods that don\'t exist in the class.',
$method,
$this->type
)
);
}
}

$this->methods = $methods;

return $this;
}

/**
* Specifies methods that don't exist in the class which you want to mock
*
* @param string[] $methods
*
* @throws RuntimeException
*/
public function addMethods(array $methods): self
{
$reflection = new \ReflectionClass($this->type);

foreach ($methods as $method) {
if ($reflection->hasMethod($method)) {
throw new RuntimeException(
\sprintf(
'Trying to set mock method "%s" with addMethod, but it exists in class "%s". Use onlyMethods() for methods that exist in the class.',
$method,
$this->type
)
Expand Down
33 changes: 26 additions & 7 deletions tests/unit/Framework/MockObject/MockBuilderTest.php
Expand Up @@ -60,30 +60,49 @@ public function testSetMethodsAllowsNonExistentMethodNames(): void
$this->assertNull($mock->mockableMethodWithCrazyName());
}

public function testSetRealMethodsWithNonExistentMethodNames(): void
public function testOnlyMethodsWithNonExistentMethodNames(): void
{
$this->expectException(RuntimeException::class);

$this->getMockBuilder(Mockable::class)
->setRealMethods(['mockableMethodWithCrazyName'])
->onlyMethods(['mockableMethodWithCrazyName'])
->getMock();
}

public function testSetRealMethodsWithExistingMethodNames(): void
public function testOnlyMethodsWithExistingMethodNames(): void
{
$mock = $this->getMockBuilder(Mockable::class)
->setRealMethods(['mockableMethod'])
->getMock();
->onlyMethods(['mockableMethod'])
->getMock();

$this->assertNull($mock->mockableMethod());
$this->assertTrue($mock->anotherMockableMethod());
}

public function testAddMethodsWithNonExistentMethodNames(): void
{
$this->expectException(RuntimeException::class);

$this->getMockBuilder(Mockable::class)
->addMethods(['mockableMethod'])
->getMock();
}

public function testAddMethodsWithExistingMethodNames(): void
{
$mock = $this->getMockBuilder(Mockable::class)
->addMethods(['mockableMethodWithFakeMethod'])
->getMock();

$this->assertNull($mock->mockableMethodWithFakeMethod());
$this->assertTrue($mock->anotherMockableMethod());
}

public function testEmptyMethodExceptionsToMockCanBeSpecified(): void
{
$mock = $this->getMockBuilder(Mockable::class)
->setMethodsExcept()
->getMock();
->setMethodsExcept()
->getMock();

$this->assertNull($mock->mockableMethod());
$this->assertNull($mock->anotherMockableMethod());
Expand Down

0 comments on commit a58c6d9

Please sign in to comment.