Skip to content

Commit

Permalink
Warn of non-existent methods in createPartialMock
Browse files Browse the repository at this point in the history
  • Loading branch information
DFoxinator committed May 15, 2019
1 parent 29f04eb commit f3b6b02
Show file tree
Hide file tree
Showing 6 changed files with 94 additions and 1 deletion.
6 changes: 5 additions & 1 deletion .psalm/baseline.xml
Expand Up @@ -223,11 +223,15 @@
<ArgumentTypeCoercion occurrences="1">
<code>$this-&gt;expectedException</code>
</ArgumentTypeCoercion>
<InvalidArgument occurrences="2">
<InvalidArgument occurrences="3">
<code>0</code>
<code>$header</code>
<code>$originalClassName</code>
</InvalidArgument>
<InvalidCatch occurrences="1"/>
<PossiblyInvalidArgument occurrences="1">
<code>$originalClassName</code>
</PossiblyInvalidArgument>
<PossiblyNullPropertyAssignmentValue occurrences="3">
<code>null</code>
<code>$beStrictAboutChangesToGlobalState</code>
Expand Down
2 changes: 2 additions & 0 deletions src/Framework/MockObject/MockBuilder.php
Expand Up @@ -182,6 +182,8 @@ public function setMethods(array $methods = null): self
{
$this->methods = $methods;

$this->alreadyUsedMockMethodConfiguration = true;

return $this;
}

Expand Down
16 changes: 16 additions & 0 deletions src/Framework/TestCase.php
Expand Up @@ -1388,6 +1388,22 @@ protected function createConfiguredMock($originalClassName, array $configuration
*/
protected function createPartialMock($originalClassName, array $methods): MockObject
{
$reflection = new \ReflectionClass($originalClassName);

$mockedMethodsThatDontExist = \array_filter($methods, function (string $method) use ($reflection) {
return !$reflection->hasMethod($method);
});

if ($mockedMethodsThatDontExist) {
$this->addWarning(
\sprintf(
'createPartialMock called with method(s) %s that do not exist in %s. This will not be allowed in future versions of PHPUnit.',
\implode(', ', $mockedMethodsThatDontExist),
$originalClassName
)
);
}

try {
return $this->getMockBuilder($originalClassName)
->disableOriginalConstructor()
Expand Down
11 changes: 11 additions & 0 deletions tests/_files/TestWithDifferentStatuses.php
Expand Up @@ -45,4 +45,15 @@ public function testThatAddsAWarning(): void
{
$this->addWarning('Sorry, Dave!');
}

public function testWithCreatePartialMockWarning(): void
{
$this->createPartialMock(\Mockable::class, ['mockableMethod', 'fakeMethod1', 'fakeMethod2']);
}

public function testWithCreatePartialMockPassesNoWarning(): void
{
$mock = $this->createPartialMock(\Mockable::class, ['mockableMethod']);
$this->assertNull($mock->mockableMethod());
}
}
40 changes: 40 additions & 0 deletions tests/unit/Framework/MockObject/MockBuilderTest.php
Expand Up @@ -128,6 +128,46 @@ public function testNotAbleToUseOnlyMethodsAfterAddMethods(): void
->getMock();
}

public function testAbleToUseSetMethodsAfterOnlyMethods(): void
{
$mock = $this->getMockBuilder(Mockable::class)
->onlyMethods(['mockableMethod'])
->setMethods(['mockableMethodWithCrazyName'])
->getMock();

$this->assertNull($mock->mockableMethodWithCrazyName());
}

public function testAbleToUseSetMethodsAfterAddMethods(): void
{
$mock = $this->getMockBuilder(Mockable::class)
->addMethods(['notAMethod'])
->setMethods(['mockableMethodWithCrazyName'])
->getMock();

$this->assertNull($mock->mockableMethodWithCrazyName());
}

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

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

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

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

public function testByDefaultDoesNotPassArgumentsToTheConstructor(): void
{
$mock = $this->getMockBuilder(Mockable::class)->getMock();
Expand Down
20 changes: 20 additions & 0 deletions tests/unit/Framework/TestCaseTest.php
Expand Up @@ -856,6 +856,26 @@ public function testCreatePartialMockCanMockNoMethods(): void
$this->assertTrue($mock->anotherMockableMethod());
}

public function testCreatePartialMockWithFakeMethods(): void
{
$test = new \TestWithDifferentStatuses('testWithCreatePartialMockWarning');

$test->run();

$this->assertSame(BaseTestRunner::STATUS_WARNING, $test->getStatus());
$this->assertFalse($test->hasFailed());
}

public function testCreatePartialMockWithRealMethods(): void
{
$test = new \TestWithDifferentStatuses('testWithCreatePartialMockPassesNoWarning');

$test->run();

$this->assertSame(BaseTestRunner::STATUS_PASSED, $test->getStatus());
$this->assertFalse($test->hasFailed());
}

public function testCreateMockSkipsConstructor(): void
{
/** @var \Mockable $mock */
Expand Down

0 comments on commit f3b6b02

Please sign in to comment.