assertCallbackInstanceOf()   C
last analyzed

Complexity

Conditions 7
Paths 2

Size

Total Lines 27
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 27
rs 6.7273
cc 7
eloc 18
nc 2
nop 3
1
<?php
2
/*
3
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
4
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
5
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
6
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
7
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
8
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
9
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
10
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
11
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
12
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
13
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
14
 *
15
 * This software consists of voluntary contributions made by many individuals
16
 * and is licensed under the MIT license. For more information, see
17
 * <http://www.doctrine-project.org>.
18
 */
19
20
namespace BaleenTest\Cli\Provider;
21
22
use Baleen\Cli\Config\Config;
23
use BaleenTest\Cli\BaseTestCase;
24
use League\Container\Container;
25
use League\Container\Definition\Factory;
26
use League\Container\ServiceProvider;
27
use Mockery as m;
28
29
/**
30
 * Class ServiceProviderTestCase
31
 * @author Gabriel Somoza <[email protected]>
32
 */
33
class ServiceProviderTestCase extends BaseTestCase
34
{
35
36
    /** @var ServiceProvider|m\Mock */
37
    protected $instance;
38
39
    /** @var m\Mock */
40
    protected $config;
41
42
    /**
43
     * @return ServiceProvider|m\Mock
44
     */
45
    public function getInstance()
46
    {
47
        return $this->instance;
48
    }
49
50
    /** @var ServiceProvider|m\Mock */
51
    protected $container;
52
53
    /**
54
     * @return ServiceProvider|m\Mock
55
     */
56
    public function getContainer()
57
    {
58
        return $this->container;
59
    }
60
61
    /**
62
     * @param ServiceProvider|m\Mock $container
63
     */
64
    public function setContainer($container)
65
    {
66
        $this->container = $container;
67
    }
68
69
    public function setUp()
70
    {
71
        parent::setUp();
72
        $this->container = m::mock(Container::class)->makePartial();
73
        $prop = new \ReflectionProperty($this->container, 'factory');
74
        $prop->setAccessible(true);
75
        $prop->setValue($this->container, new Factory());
76
77
        $config = m::mock(Config::class);
78
        $this->config = $config;
79
    }
80
81
    public function tearDown()
82
    {
83
        parent::tearDown();
84
        $this->instance = null;
85
        $this->container = null;
86
    }
87
88
    /**
89
     * @param m\Mock $instance
90
     */
91
    protected function setInstance($instance)
92
    {
93
        $this->instance = $instance;
94
        $this->instance->shouldReceive('getContainer')->zeroOrMoreTimes()->andReturn($this->getContainer());
95
    }
96
97
98
    /**
99
     * @param $service
100
     * @param \Closure $callback
101
     * @param string $concreteType
102
     * @return m\Mock
103
     */
104
    public function assertSingletonProvided($service, $callback, $concreteType = 'callable')
105
    {
106
        $this->assertServiceProvided($service, 'singleton', $callback, $concreteType);
107
        return $this->getContainer();
108
    }
109
110
    /**
111
     * @param $service
112
     * @param string $type
113
     * @param \Closure $callback
114
     * @param string $concreteType
115
     * @return m\Mock
116
     */
117
    protected function assertServiceProvided($service, $type, $callback, $concreteType = 'callable')
118
    {
119
        $this->getContainer()->shouldReceive($type)->with($service, m::type($concreteType))->once()
120
            ->andReturnUsing($callback);
121
        return $this->getContainer();
122
    }
123
124
    /**
125
     * Returns a closure that validates whether the result of a service factory callback is an instance of the
126
     * specified $instanceOf class.
127
     *
128
     * @param $instanceOf
129
     * @param array $factoryArgs
130
     * @return \Closure
131
     */
132
    protected function assertCallbackInstanceOf($instanceOf, $factoryArgs = [], \Closure $additionalAssertions = null) {
133
        if ($factoryArgs && !is_array($factoryArgs)) {
134
            $factoryArgs = [$factoryArgs];
135
        }
136
        return $this->assertableCallback(
137
            function($factory) use ($instanceOf, $factoryArgs, $additionalAssertions) {
138
                if (is_string($factory)) {
139
                    // simulate the Container's behaviour when a string is supplied as a concrete
140
                    $factory = function () use ($factory) {
141
                        $refl = new \ReflectionClass($factory);
142
                        return $refl->newInstanceArgs(func_get_args());
143
                    };
144
                }
145
                if (is_object($factory) && $factory instanceof \Closure) {
146
                    $factory = $factory->bindTo($this);
147
                }
148
                $func = [$factory, '__invoke'];
149
                $result = call_user_func_array($func, $factoryArgs);
150
                $this->assertInstanceOf($instanceOf, $result);
151
                if (null !== $additionalAssertions) {
152
                    $additionalAssertions = $additionalAssertions->bindTo($this);
153
                    $additionalAssertions->__invoke($result);
154
                }
155
                return $this->getContainer();
156
            }
157
        );
158
    }
159
160
    /**
161
     * Returns a closure that calls $callback with scope $this (this test case object), passing the service $factory
162
     * as the first argument.
163
     *
164
     * @param \Closure $callback
165
     * @return \Closure
166
     */
167
    protected function assertableCallback($callback)
168
    {
169
        $self = $this;
170
        return function() use ($self, $callback) {
171
            /** @var \Closure $callback */
172
            list(, $factory) = func_get_args();
173
            $callback = $callback->bindTo($self, $factory);
174
            return $callback->__invoke($factory);
175
        };
176
    }
177
178
    /**
179
     * @param $name
180
     */
181
    protected function assertRegistersProvider($name)
182
    {
183
        $this->getContainer()->shouldReceive('addServiceProvider')->with($name)->once();
184
    }
185
186
    /**
187
     * @param $name
188
     * @param array $withMethods
189
     */
190
    protected function assertRegistersInflector($name, $withMethods = [])
191
    {
192
        $definitionMock = m::mock();
193
        if (count($withMethods) == 1) {
194
            $methodName = 'invokeMethod';
195
            $withMethods = [key($withMethods), current($withMethods)];
196
        } else {
197
            $methodName = 'invokeMethods';
198
            $withMethods = [$withMethods];
199
        }
200
        $exp = $definitionMock->shouldReceive($methodName)->once();
201
        $exp = call_user_func_array([$exp, 'with'], $withMethods);
202
        $exp->andReturn($definitionMock);
203
204
        $this->getContainer()->shouldReceive('inflector')->with($name)->once()->andReturn($definitionMock);
205
    }
206
}
207