Skip to content

Commit

Permalink
#3120 implemented TestCase#createStub()
Browse files Browse the repository at this point in the history
  • Loading branch information
Ocramius authored and sebastianbergmann committed Sep 6, 2019
1 parent f5ea88f commit f0d4aee
Show file tree
Hide file tree
Showing 6 changed files with 107 additions and 13 deletions.
12 changes: 4 additions & 8 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 @@ -68,7 +68,7 @@ public function id($id): self
return $this;
}

public function will(Stub $stub): Identity
public function will(Stub $stub): self
{
$this->matcher->setStub($stub);

Expand All @@ -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
44 changes: 44 additions & 0 deletions src/Framework/MockObject/Builder/InvocationStubber.php
@@ -0,0 +1,44 @@
<?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
{
/**
* @TODO is "will" actually sensible in a stub context? Should a stub produce side-effects?
*
* Note: probably yes, since you want a stub of a promise to be able to resolve a real callback, for example
*/
public function will(Stub $stub): Identity;

public function willReturn($value, ...$nextValues): self;

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

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

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

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

public function willReturnSelf(): self;

/** @param mixed $values */
public function willReturnOnConsecutiveCalls(...$values): 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\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

0 comments on commit f0d4aee

Please sign in to comment.