Completed
Pull Request — master (#41)
by Thomas
03:37
created

MockTrait   A

Complexity

Total Complexity 10

Size/Duplication

Total Lines 110
Duplicated Lines 0 %

Coupling/Cohesion

Components 0
Dependencies 6

Importance

Changes 1
Bugs 0 Features 1
Metric Value
wmc 10
c 1
b 0
f 1
lcom 0
cbo 6
dl 0
loc 110
rs 10

3 Methods

Rating   Name   Duplication   Size   Complexity  
A emInitMock() 0 16 1
B emExpectInsert() 0 30 6
A emExpectFetch() 0 17 3
1
<?php
2
3
namespace ORM;
4
5
use Mockery as m;
6
use Mockery\Mock;
7
use ORM\Exception\IncompletePrimaryKey;
8
9
trait MockTrait
10
{
11
12
    /**
13
     * Initialize an EntityManager mock object
14
     *
15
     * The mock is partial and you can map and act with it as usual. You should overwrite your dependency injector
16
     * with the returned mock object. You can also call `defineFor*()` on this mock to use this mock for specific
17
     * classes.
18
     *
19
     * The PDO object is mocked too. This object should not receive any calls except for quoting. By default it
20
     * accepts `quote(string)`, `setAttribute(*)` and `getAttribute(ATTR_DRIVER_NAME)`. To retrieve and expect other
21
     * calls you can use `getConnection()` from EntityManager mock object.
22
     *
23
     * @param array  $options Options passed to EntityManager constructor
24
     * @param string $driver  Database driver you are using (results in different dbal instance)
25
     * @return Mock|EntityManager
26
     */
27
    public function emInitMock($options = [], $driver = 'mysql')
28
    {
29
        /** @var EntityManager|Mock $em */
30
        $em = m::mock(EntityManager::class, [$options])->makePartial();
31
        /** @var \PDO|Mock $pdo */
32
        $pdo = m::mock(\PDO::class);
33
34
        $pdo->shouldReceive('setAttribute')->andReturn(true)->byDefault();
0 ignored issues
show
Bug introduced by
The method shouldReceive does only exist in Mockery\Mock, but not in PDO.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
35
        $pdo->shouldReceive('getAttribute')->with(\PDO::ATTR_DRIVER_NAME)->andReturn($driver)->byDefault();
36
        $pdo->shouldReceive('quote')->with(stringValue())->andReturnUsing(function ($str) {
37
            return '\'' . addcslashes($str, '\'') . '\'';
38
        })->byDefault();
39
40
        $em->setConnection($pdo);
0 ignored issues
show
Bug introduced by
The method setConnection does only exist in ORM\EntityManager, but not in Mockery\Mock.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
41
        return $em;
42
    }
43
44
    /**
45
     * Expect an insert for $class
46
     *
47
     * Mocks and expects the calls to sync and insert as they came for `save()` method for a new Entity.
48
     *
49
     * If you omit the auto incremented id in defaultValues it is set to a random value between 1 and 2147483647.
50
     *
51
     * The EntityManager gets determined the same way as in Entity and can be overwritten by third parameter here.
52
     *
53
     * @param string        $class         The class that should get created
54
     * @param array         $defaultValues The default values that came from database (for example: the created column
55
     *                                     has by the default the current timestamp; the id is auto incremented...)
56
     * @param EntityManager $em
57
     * @throws Exception
58
     */
59
    public function emExpectInsert($class, $defaultValues = [], $em = null)
60
    {
61
        /** @var EntityManager|Mock $em */
62
        $em = $em ?: EntityManager::getInstance($class);
63
64
        if (!is_callable([$em, 'shouldReceive'])) {
65
            throw new Exception('EntityManager mock not initialized');
66
        }
67
68
        $em->shouldReceive('sync')->with(m::type($class))->once()
0 ignored issues
show
Bug introduced by
The method shouldReceive does only exist in Mockery\Mock, but not in ORM\EntityManager.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
69
            ->andReturnUsing(function (Entity $entity, $reset = false) {
0 ignored issues
show
Unused Code introduced by
The parameter $reset is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
70
                $entity->getPrimaryKey(); // this may throw
71
                return false;
72
            });
73
74
        $em->shouldReceive('insert')->with(m::on(function ($entity, $useAutoIncrement = true) use ($class) {
0 ignored issues
show
Bug introduced by
The method shouldReceive does only exist in Mockery\Mock, but not in ORM\EntityManager.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
Unused Code introduced by
The parameter $useAutoIncrement is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
75
            if ($entity instanceof $class) {
76
                return true;
77
            }
78
            return false;
79
        }))->once()->andReturnUsing(function (Entity $entity, $useAutoIncrement = true) use ($defaultValues, $em) {
80
            if ($useAutoIncrement && !isset($defaultValues[$entity::getPrimaryKeyVars()[0]])) {
81
                $defaultValues[$entity::getPrimaryKeyVars()[0]] = mt_rand(1, pow(2, 31) - 1);
82
            }
83
            $entity->setOriginalData(array_merge($defaultValues, $entity->getData()));
84
            $entity->reset();
85
            $em->map($entity);
0 ignored issues
show
Bug introduced by
The method map does only exist in ORM\EntityManager, but not in Mockery\Mock.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
86
            return true;
87
        });
88
    }
89
90
    /**
91
     * Expect fetch for $class
92
     *
93
     * Mocks and expects an EntityFetcher with $entities as result.
94
     *
95
     * @param string        $class    The class that should be fetched
96
     * @param array         $entities The entities that get returned from fetcher
97
     * @param EntityManager $em
98
     * @return Mock
99
     * @throws Exception
100
     */
101
    public function emExpectFetch($class, $entities = [], $em = null)
102
    {
103
        /** @var EntityManager|Mock $em */
104
        $em = $em ?: EntityManager::getInstance($class);
105
106
        if (!is_callable([$em, 'shouldReceive'])) {
107
            throw new Exception('EntityManager mock not initialized');
108
        }
109
110
        $fetcher = \Mockery::mock(EntityFetcher::class, [$em, $class])->makePartial();
111
        $em->shouldReceive('fetch')->with($class)->once()->andReturn($fetcher);
0 ignored issues
show
Bug introduced by
The method shouldReceive does only exist in Mockery\Mock, but not in ORM\EntityManager.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
112
113
        $fetcher->shouldReceive('one')->with()->andReturnValues($entities)->byDefault();
114
        $fetcher->shouldReceive('count')->with()->andReturn(count($entities))->byDefault();
115
116
        return $fetcher;
117
    }
118
}
119