Passed
Pull Request — master (#14)
by Alex
02:11
created

testInvokeWillThrowEventListenerExceptionIfLoadedListenerIsNotCallable()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 19
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 10
c 0
b 0
f 0
dl 0
loc 19
rs 9.9332
cc 1
nc 1
nop 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace ArpTest\EventDispatcher\Listener;
6
7
use Arp\EventDispatcher\Listener\Exception\EventListenerException;
8
use Arp\EventDispatcher\Listener\LazyListener;
9
use PHPUnit\Framework\MockObject\MockObject;
10
use PHPUnit\Framework\TestCase;
11
12
/**
13
 * @author  Alex Patterson <[email protected]>
14
 * @package ArpTest\EventDispatcher\Listener
15
 */
16
final class LazyListenerTest extends TestCase
17
{
18
    /**
19
     * testIsCallable
20
     *
21
     * @covers \Arp\EventDispatcher\Listener\LazyListener::__construct
22
     */
23
    public function testIsCallable(): void
24
    {
25
        $listener = new LazyListener(\stdClass::class, []);
26
27
        $this->assertIsCallable($listener);
28
    }
29
30
    /**
31
     * Assert that a new EventListenerException will be thrown if the lazy loaded event listener is not callable.
32
     *
33
     * @covers \Arp\EventDispatcher\Listener\LazyListener::__invoke
34
     */
35
    public function testInvokeWillThrowEventListenerExceptionIfLoadedListenerIsNotCallable(): void
36
    {
37
        $className = \stdClass::class;
38
39
        $factory = static function () {
40
            return false; // our result is not a callable type.
41
        };
42
43
        $listener = new LazyListener($className, [], $factory);
44
45
        $this->expectException(EventListenerException::class);
46
        $this->expectExceptionMessage(sprintf(
47
            'The the lazy loaded event listener, using class \'%s\', is not callable.',
48
            $className
49
        ));
50
51
        $event = new \stdClass();
52
53
        $listener($event);
54
    }
55
56
    /**
57
     * Assert that the event listener will be created and invoked.
58
     *
59
     * @covers \Arp\EventDispatcher\Listener\LazyListener::__invoke
60
     */
61
    public function testInvokeWillCreateAndInvokeTheLazyEventListener(): void
62
    {
63
        $expectedClassName = \stdClass::class;
64
65
        $expectedEvent = new \stdClass();
66
        $expectedArgs = ['hello' => 'foo'];
67
68
        $mockedListener = function ($passedEvent) use ($expectedEvent) {
69
            $this->assertSame($passedEvent, $expectedEvent);
70
        };
71
72
        $factory = function ($className, $arguments) use ($mockedListener, $expectedArgs, $expectedClassName) {
73
            $this->assertSame($expectedClassName, $className);
74
            $this->assertSame($expectedArgs, $arguments);
75
            return $mockedListener;
76
        };
77
78
        $lazyListener = new LazyListener($expectedClassName, $expectedArgs, $factory);
79
80
        $lazyListener($expectedEvent);
81
    }
82
83
    /**
84
     * Assert that the default factory will be used if no factory has been provided to the.
85
     *
86
     * @throws EventListenerException
87
     *
88
     * @covers \Arp\EventDispatcher\Listener\LazyListener::__invoke
89
     */
90
    public function testDefaultFactoryWillBeUsedWhenOneIsNotProvidedViaConstruct(): void
91
    {
92
        $expectedClassName = 'Foo';
93
        $expectedArguments = ['foo' => 'bar', 'bar' => 123];
94
95
        $expectedEvent = new \stdClass();
96
97
        $defaultListener = function (object $event) use ($expectedEvent) {
98
            $this->assertSame($expectedEvent, $event);
99
        };
100
101
        $defaultListenerFactory = function (
102
            string $className,
103
            array $arguments = []
104
        ) use (
105
            $expectedClassName,
106
            $expectedArguments,
107
            $defaultListener
108
        ) {
109
            $this->assertSame($expectedClassName, $className);
110
            $this->assertSame($expectedArguments, $arguments);
111
112
            return $defaultListener;
113
        };
114
115
        /** @var LazyListener|MockObject $lazyListener */
116
        $lazyListener = $this->getMockBuilder(LazyListener::class)
117
            ->setConstructorArgs([$expectedClassName, $expectedArguments])
118
            ->onlyMethods(['getDefaultListenerFactory'])
119
            ->getMock();
120
121
        $lazyListener->expects($this->once())
122
            ->method('getDefaultListenerFactory')
123
            ->willReturn($defaultListenerFactory);
124
125
        $lazyListener($expectedEvent);
126
    }
127
128
    /**
129
     * Assert that the defaultFactory is created and lazy loaded listener is executed correctly.
130
     *
131
     * @return void
132
     */
133
    public function testDefaultFactoryCreatesAndInvokesLazyListenerMock(): void
134
    {
135
        $event = new \stdClass();
136
137
        $className = LazyListenerMock::class;
138
        $arguments = [
139
            $event, // bit of a hack but we need $event in the fake listener to assert something...
140
            'foo' => 'bar',
141
            'test' => 123,
142
        ];
143
144
        $lazyListener = new LazyListener($className, $arguments);
145
146
        $lazyListener($event);
147
    }
148
}
149