Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#3120 implemented TestCase#createStub() #3810

Merged
merged 10 commits into from Sep 6, 2019
7 changes: 7 additions & 0 deletions .phpstorm.meta.php
Expand Up @@ -8,6 +8,13 @@
])
);

override(
\PHPUnit\Framework\TestCase::createStub(0),
map([
'@&\PHPUnit\Framework\MockObject\Stub',
])
);

override(
\PHPUnit\Framework\TestCase::createConfiguredMock(0),
map([
Expand Down
14 changes: 4 additions & 10 deletions .psalm/baseline.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<files psalm-version="3.x-dev@0279c6f6d9bbe22854526c45eaf1f5482c12ade3">
<files psalm-version="3.4.12@86e5e50c1bb492045e70f2ebe1da3cad06e4e9b2">
<file src="src/Framework/Assert.php">
<ArgumentTypeCoercion occurrences="2">
<code>$expectedElement-&gt;childNodes-&gt;item($i)</code>
Expand Down Expand Up @@ -397,9 +397,7 @@
</UndefinedInterfaceMethod>
</file>
<file src="src/Util/Log/TeamCity.php">
<ArgumentTypeCoercion occurrences="3">
<code>$split[0]</code>
<code>$split[0]</code>
<ArgumentTypeCoercion occurrences="1">
<code>$className</code>
</ArgumentTypeCoercion>
<UndefinedInterfaceMethod occurrences="7">
Expand Down Expand Up @@ -455,18 +453,14 @@
</PossiblyNullArgument>
</file>
<file src="src/Util/Test.php">
<ArgumentTypeCoercion occurrences="5">
<ArgumentTypeCoercion occurrences="4">
<code>$className</code>
<code>$pieces[0]</code>
<code>$className</code>
<code>$className</code>
<code>$dataProviderClassName</code>
</ArgumentTypeCoercion>
<InvalidArgument occurrences="4">
<InvalidArgument occurrences="1">
<code>$e</code>
<code>$operator</code>
<code>$operator</code>
<code>$operator</code>
</InvalidArgument>
<InvalidCatch occurrences="1"/>
<InvalidReturnStatement occurrences="1">
Expand Down
10 changes: 3 additions & 7 deletions src/Framework/MockObject/Builder/InvocationMocker.php
Expand Up @@ -29,7 +29,7 @@
/**
* @internal This class is not covered by the backward compatibility promise for PHPUnit
*/
final class InvocationMocker implements MethodNameMatch
final class InvocationMocker implements InvocationStubber, MethodNameMatch
{
/**
* @var MatcherCollection
Expand Down Expand Up @@ -92,9 +92,7 @@ public function willReturn($value, ...$nextValues): self
return $this->will($stub);
}

/**
* @param mixed $reference
*/
/** {@inheritDoc} */
public function willReturnReference(&$reference): self
{
$stub = new ReturnReference($reference);
Expand All @@ -116,9 +114,7 @@ public function willReturnArgument($argumentIndex): self
return $this->will($stub);
}

/**
* @param callable $callback
*/
/** {@inheritDoc} */
public function willReturnCallback($callback): self
{
$stub = new ReturnCallback($callback);
Expand Down
62 changes: 62 additions & 0 deletions src/Framework/MockObject/Builder/InvocationStubber.php
@@ -0,0 +1,62 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PHPUnit\Framework\MockObject\Builder;

use PHPUnit\Framework\MockObject\Stub\Stub;

/** @internal This class is not covered by the backward compatibility promise for PHPUnit */
interface InvocationStubber
{
public function will(Stub $stub): Identity;

/** @return self */
public function willReturn($value, ...$nextValues) /*: self */;

/**
* @param mixed $reference
*
* @return self
*/
public function willReturnReference(&$reference) /*: self */;

/**
* @param array<int, array<int, mixed>> $valueMap
*
* @return self
*/
public function willReturnMap(array $valueMap) /*: self */;

/**
* @param int $argumentIndex
*
* @return self
*/
public function willReturnArgument($argumentIndex) /*: self */;

/**
* @param callable $callback
*
* @return self
*/
public function willReturnCallback($callback) /*: self */;

/** @return self */
public function willReturnSelf() /*: self */;

/**
* @param mixed $values
*
* @return self
*/
public function willReturnOnConsecutiveCalls(...$values) /*: self */;

/** @return self */
public function willThrowException(\Throwable $exception) /*: self */;
}
4 changes: 2 additions & 2 deletions src/Framework/MockObject/Stub.php
Expand Up @@ -9,10 +9,10 @@
*/
namespace PHPUnit\Framework\MockObject;

use PHPUnit\Framework\MockObject\Builder\InvocationMocker as BuilderInvocationMocker;
use PHPUnit\Framework\MockObject\Builder\InvocationStubber;

/**
* @method BuilderInvocationMocker method($constraint)
* @method InvocationStubber method($constraint)
*/
interface Stub
{
Expand Down
13 changes: 13 additions & 0 deletions src/Framework/TestCase.php
Expand Up @@ -27,6 +27,7 @@
use PHPUnit\Framework\MockObject\Matcher\InvokedCount as InvokedCountMatcher;
use PHPUnit\Framework\MockObject\MockBuilder;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\MockObject\Stub;
use PHPUnit\Framework\MockObject\Stub\ConsecutiveCalls as ConsecutiveCallsStub;
use PHPUnit\Framework\MockObject\Stub\Exception as ExceptionStub;
use PHPUnit\Framework\MockObject\Stub\ReturnArgument as ReturnArgumentStub;
Expand Down Expand Up @@ -1543,6 +1544,18 @@ protected function setLocale(...$args): void
}
}

/**
* Makes configurable stub for the specified class.
*
* @psalm-template RealInstanceType of object
* @psalm-param class-string<RealInstanceType> $originalClassName
* @psalm-return Stub&RealInstanceType
*/
protected function createStub(string $originalClassName): Stub
{
return $this->createMock($originalClassName);
}

/**
* Returns a test double for the specified class.
*
Expand Down
11 changes: 11 additions & 0 deletions tests/static-analysis/TestUsingMocks.php
Expand Up @@ -35,6 +35,17 @@ public function testWillSayHelloThroughCreateMock(): void
self::assertSame('hello mock!', $mock->sayHello());
}

public function testWillSayHelloThroughCreateStub(): void
{
$mock = $this->createStub(HelloWorldClass::class);

$mock
->method('sayHello')
->willReturn('hello mock!');

self::assertSame('hello mock!', $mock->sayHello());
}

public function testWillSayHelloThroughCreateConfiguredMock(): void
{
$mock = $this->createConfiguredMock(HelloWorldClass::class, []);
Expand Down
36 changes: 33 additions & 3 deletions tests/unit/Framework/TestCaseTest.php
Expand Up @@ -10,6 +10,7 @@
namespace PHPUnit\Framework;

use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\MockObject\Stub;
use PHPUnit\Runner\BaseTestRunner;
use PHPUnit\Util\Test as TestUtil;

Expand Down Expand Up @@ -832,13 +833,28 @@ public function testCreateMockFromClassName(): void

public function testCreateMockMocksAllMethods(): void
{
/** @var \Mockable $mock */
$mock = $this->createMock(\Mockable::class);

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

public function testCreateStubFromClassName(): void
{
$mock = $this->createStub(\Mockable::class);

$this->assertInstanceOf(\Mockable::class, $mock);
$this->assertInstanceOf(Stub::class, $mock);
}

public function testCreateStubMocksAllMethods(): void
{
$mock = $this->createStub(\Mockable::class);

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

public function testCreatePartialMockDoesNotMockAllMethods(): void
{
/** @var \Mockable $mock */
Expand Down Expand Up @@ -879,21 +895,34 @@ public function testCreatePartialMockWithRealMethods(): void

public function testCreateMockSkipsConstructor(): void
{
/** @var \Mockable $mock */
$mock = $this->createMock(\Mockable::class);

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

public function testCreateMockDisablesOriginalClone(): void
{
/** @var \Mockable $mock */
$mock = $this->createMock(\Mockable::class);

$cloned = clone $mock;
$this->assertNull($cloned->cloned);
}

public function testCreateStubSkipsConstructor(): void
{
$mock = $this->createStub(\Mockable::class);

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

public function testCreateStubDisablesOriginalClone(): void
{
$mock = $this->createStub(\Mockable::class);

$cloned = clone $mock;
$this->assertNull($cloned->cloned);
}

public function testConfiguredMockCanBeCreated(): void
{
/** @var \Mockable $mock */
Expand Down Expand Up @@ -924,6 +953,7 @@ public function testProvidingArrayThatMixesObjectsAndScalars(): void
[123],
['foo'],
[$this->createMock(\Mockable::class)],
[$this->createStub(\Mockable::class)],
];

$test = new \TestAutoreferenced('testJsonEncodeException', [$data]);
Expand Down