Skip to content

Commit

Permalink
Allow using prophecy in test attributes as well
Browse files Browse the repository at this point in the history
  • Loading branch information
lcobucci authored and ondrejmirtes committed Jul 26, 2018
1 parent 9177e63 commit 3953120
Show file tree
Hide file tree
Showing 5 changed files with 137 additions and 43 deletions.
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"php": "^7.1",
"phpspec/prophecy": "^1.7",
"phpunit/phpunit": "^6.0||^7.0",
"phpstan/phpstan": "^0.10"
"phpstan/phpstan": "^0.10.3@dev"
},
"autoload": {
"psr-4": {
Expand Down
85 changes: 44 additions & 41 deletions composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

61 changes: 61 additions & 0 deletions src/PhpDoc/TypeNodeResolverExtension.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<?php

namespace JanGregor\Prophecy\PhpDoc;

use JanGregor\Prophecy\Type\ObjectProphecyType;
use PHPStan\Analyser\NameScope;
use PHPStan\PhpDoc\TypeNodeResolver;
use PHPStan\PhpDoc\TypeNodeResolverAwareExtension;
use PHPStan\PhpDocParser\Ast\Type\TypeNode;
use PHPStan\PhpDocParser\Ast\Type\UnionTypeNode;
use PHPStan\Type\Type;
use PHPStan\Type\TypeWithClassName;
use Prophecy\Prophecy\ObjectProphecy;

class TypeNodeResolverExtension implements \PHPStan\PhpDoc\TypeNodeResolverExtension, TypeNodeResolverAwareExtension
{

/** @var TypeNodeResolver */
private $typeNodeResolver;

public function setTypeNodeResolver(TypeNodeResolver $typeNodeResolver): void
{
$this->typeNodeResolver = $typeNodeResolver;
}

public function getCacheKey(): string
{
return 'prophecy-v1';
}

public function resolve(TypeNode $typeNode, NameScope $nameScope): ?Type
{
if (!$typeNode instanceof UnionTypeNode) {
return null;
}

if (count($typeNode->types) === 2) {
$objectProphecyType = null;
$prophesizedType = null;
foreach ($typeNode->types as $innerType) {
$type = $this->typeNodeResolver->resolve($innerType, $nameScope);
if ($type instanceof TypeWithClassName) {
if ($type->getClassName() === ObjectProphecy::class) {
$objectProphecyType = $type;
} else {
$prophesizedType = $type;
}
} else {
break;
}
}

if ($objectProphecyType !== null && $prophesizedType !== null) {
return new ObjectProphecyType($prophesizedType->getClassName());
}
}

return null;
}

}
5 changes: 5 additions & 0 deletions src/extension.neon
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,8 @@ services:
class: JanGregor\Prophecy\Reflection\ProphecyMethodsClassReflectionExtension
tags:
- phpstan.broker.methodsClassReflectionExtension

-
class: JanGregor\Prophecy\PhpDoc\TypeNodeResolverExtension
tags:
- phpstan.phpDoc.typeNodeResolverExtension
27 changes: 26 additions & 1 deletion tests/Test/BaseModelTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,18 @@

namespace Tests\Test;

use Tests\Model\BaseModel;
use PHPUnit\Framework\TestCase;
use Prophecy\Argument;
use Prophecy\Prophecy\ObjectProphecy;
use Tests\Model\BaseModel;

class BaseModelTest extends TestCase
{
/**
* @var BaseModel|ObjectProphecy
*/
private $subject;

public function testBasicProperty()
{
$word = 'bar';
Expand All @@ -29,4 +35,23 @@ public function testWithProphecy()
$this->assertEquals('bar', $subject->reveal()->getFoo());
$this->assertEquals(5, $subject->reveal()->doubleTheNumber(2));
}

/**
* @before
*/
public function createSubject(): void
{
$this->subject = $this->prophesize(BaseModel::class);
}

public function testProphesizedAttributesShouldAlsoWork(): void
{
$this->subject->getFoo()->willReturn('bar');
$this->subject->doubleTheNumber(Argument::is(2))->willReturn(5);

$subject = $this->subject->reveal();

$this->assertEquals('bar', $subject->getFoo());
$this->assertEquals(5, $subject->doubleTheNumber(2));
}
}

0 comments on commit 3953120

Please sign in to comment.