Completed
Push — master ( 916c4f...7f572e )
by Benedikt
06:01
created

UnitTestCase::getEntityManagerMockForQuery()   B

Complexity

Conditions 2
Paths 1

Size

Total Lines 27
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 19
c 0
b 0
f 0
nc 1
nop 4
dl 0
loc 27
rs 8.8571
1
<?php
2
declare(strict_types=1);
3
/**
4
 * Created by PhpStorm.
5
 * User: benedikt
6
 * Date: 1/6/18
7
 * Time: 7:08 PM
8
 */
9
10
namespace Tfboe\FmLib\TestHelpers;
11
12
use Doctrine\ORM\AbstractQuery;
13
use Doctrine\ORM\EntityManager;
14
use Doctrine\ORM\QueryBuilder;
15
use PHPUnit\Framework\MockObject\MockObject;
16
use PHPUnit\Framework\TestCase;
17
18
/**
19
 * Class UnitTestCase
20
 * @package Tfboe\FmLib\TestHelpers
21
 */
22
abstract class UnitTestCase extends TestCase
23
{
24
  use ReflectionMethods;
25
  use OnlyTestLogging;
26
27
//<editor-fold desc="Protected Methods">
28
29
  /**
30
   * Creates a stub with a given set of stubbed methods, which will return the given results
31
   * @param string $class the class name
32
   * @param array $methodResults a dictionary mapping method names to results of this methods
33
   * @return MockObject the configured stub
34
   */
35
  protected function createStub(string $class, array $methodResults): MockObject
36
  {
37
    $entity = $this->createMock($class);
38
    foreach ($methodResults as $method => $result) {
39
      $entity->method($method)->willReturn($result);
40
    }
41
    return $entity;
42
  }
43
44
  /**
45
   * Creates an empty mock with a getId method
46
   * @param string $class the class to mock
47
   * @param string $entityId the id to assign
48
   * @param string $getterMethod the name of the getter method
49
   * @return \PHPUnit\Framework\MockObject\MockObject the mocked instance
50
   */
51
  protected function createStubWithId(string $class, $entityId = "entity-id", $getterMethod = 'getId')
52
  {
53
    return $this->createStub($class, [$getterMethod => $entityId]);
54
  }
55
56
  /**
57
   * Gets a mock for an entity manager which creates a query builder which will return a query which will return the
58
   * given result.
59
   * @param array $result the result array the query should return
60
   * @param string|null $expectedQuery the expected query if set
61
   * @param string[] $otherMockedMethods list of other methods to mock
62
   * @return MockObject the mocked entity manager
63
   */
64
  protected function getEntityManagerMockForQuery(array $result, ?string $expectedQuery = null,
65
                                                  array $otherMockedMethods = [], $amount = 1)
66
  {
67
    $entityManager = $this->getMockForAbstractClass(EntityManager::class, [], '',
68
      false, true, true, array_merge($otherMockedMethods, ['createQueryBuilder']));
69
70
    $entityManager->expects(static::exactly($amount))->method('createQueryBuilder')->willReturnCallback(
71
      function () use ($entityManager, $result, $expectedQuery) {
72
        $queryBuilder = $this->getMockForAbstractClass(QueryBuilder::class, [$entityManager],
73
          '', true, true, true, ['getQuery']);
74
        $query = $this->createMock(AbstractQuery::class);
75
        $query->expects(static::once())->method('getResult')->willReturn($result);
76
        if ($expectedQuery !== null) {
77
          $queryBuilder->expects(static::once())->method('getQuery')->willReturnCallback(
78
            function () use ($queryBuilder, $query, $expectedQuery) {
79
              /** @var QueryBuilder $queryBuilder */
80
              self::assertEquals($expectedQuery, $queryBuilder->getDQL());
81
              return $query;
82
            });
83
        } else {
84
          $queryBuilder->expects(static::once())->method('getQuery')->willReturn($query);
85
        }
86
        return $queryBuilder;
87
      }
88
    );
89
    return $entityManager;
90
  }
91
92
  /** @noinspection PhpDocMissingThrowsInspection */
93
  /**
94
   * Gets a mock class (with full implementation). The given arguments are used for the arguments for the constructor.
95
   * If too less arguments are given mocks are created for the rest of the constructor arguments.
96
   * @param string $className the class to mock
97
   * @param array $arguments the arguments to use for the constructor
98
   * @param string[] $mockedMethods the methods to mock in the class
99
   * @return MockObject the mocked object
100
   */
101
  protected final function getMockWithMockedArguments(string $className, array $arguments = [],
0 ignored issues
show
Coding Style introduced by
As per PSR2, final should precede the visibility keyword.
Loading history...
102
                                                      array $mockedMethods = []): MockObject
103
  {
104
    /** @noinspection PhpUnhandledExceptionInspection */
105
    $reflection = new \ReflectionClass($className);
106
    $params = $reflection->getConstructor()->getParameters();
107
    $allArguments = $arguments;
108
    for ($i = count($arguments); $i < count($params); $i++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
109
      $allArguments[] = $this->createMock($params[$i]->getClass()->name);
110
    }
111
    return $this->getMockForAbstractClass($className, $allArguments, '', true, true, true, $mockedMethods);
112
  }
113
114
  /** @noinspection PhpDocMissingThrowsInspection */
115
  /**
116
   * Gets a new instance of the given class. The given arguments are used for the arguments for the constructor.
117
   * If too less arguments are given mocks are created for the rest of the constructor arguments.
118
   * @param string $className the class for which to create an instance
119
   * @param array $arguments the arguments to use for the constructor
120
   * @return mixed an instance of the given class
121
   */
122
  protected final function getObjectWithMockedArguments($className, array $arguments = [])
0 ignored issues
show
Coding Style introduced by
As per PSR2, final should precede the visibility keyword.
Loading history...
123
  {
124
    /** @noinspection PhpUnhandledExceptionInspection */
125
    $reflection = new \ReflectionClass($className);
126
    $params = $reflection->getConstructor()->getParameters();
127
    $allArguments = $arguments;
128
    for ($i = count($arguments); $i < count($params); $i++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
129
      $allArguments[$i] = $this->createMock($params[$i]->getClass()->name);
130
    }
131
    return new $className(...$allArguments);
132
  }
133
134
  public function tearDown()
135
  {
136
    parent::tearDown();
137
  }
138
//</editor-fold desc="Protected Methods">
139
}