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
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
Ocramius marked this conversation as resolved.
Show resolved Hide resolved
{
$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?
Ocramius marked this conversation as resolved.
Show resolved Hide resolved
*
* 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