• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

tempestphp / tempest-framework / 14180031231

31 Mar 2025 07:42PM UTC coverage: 81.035% (+0.07%) from 80.964%
14180031231

Pull #1103

github

web-flow
Merge a0ac1bfe6 into 80e661e93
Pull Request #1103: feat(event-bus): add event bus testing utilities

56 of 57 new or added lines in 3 files covered. (98.25%)

11114 of 13715 relevant lines covered (81.04%)

102.07 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

98.0
/src/Tempest/EventBus/src/Testing/EventBusTester.php
1
<?php
2

3
namespace Tempest\EventBus\Testing;
4

5
use BackedEnum;
6
use Closure;
7
use PHPUnit\Framework\Assert;
8
use PHPUnit\Framework\ExpectationFailedException;
9
use PHPUnit\Framework\GeneratorNotSupportedException;
10
use Tempest\Container\Container;
11
use Tempest\EventBus\EventBus;
12
use Tempest\EventBus\EventBusConfig;
13
use UnitEnum;
14

15
final class EventBusTester
16
{
17
    private FakeEventBus $fakeEventBus;
18

19
    public function __construct(
723✔
20
        private readonly Container $container,
21
    ) {}
723✔
22

23
    /**
24
     * Prevents the registered event handlers from being called.
25
     */
26
    public function preventEventHandling(): self
14✔
27
    {
28
        $this->fakeEventBus = new FakeEventBus($this->container->get(EventBusConfig::class));
14✔
29
        $this->container->singleton(EventBus::class, $this->fakeEventBus);
14✔
30

31
        return $this;
14✔
32
    }
33

34
    /**
35
     * Asserts that the given `$event` has been dispatched.
36
     *
37
     * @param null|Closure $callback A callback accepting the event instance. The assertion fails if the callback returns `false`.
38
     * @param null|int $count If specified, the assertion fails if the event has been dispatched a different amount of times.
39
     */
40
    public function assertDispatched(string|object $event, ?Closure $callback = null, ?int $count = null): self
7✔
41
    {
42
        $this->assertFaked();
7✔
43

44
        Assert::assertNotNull(
6✔
45
            actual: $dispatches = $this->findDispatches($event),
6✔
46
            message: 'The event was not dispatched.',
6✔
47
        );
6✔
48

49
        if ($count !== null) {
6✔
50
            Assert::assertCount($count, $dispatches, 'The number of dispatches does not match.');
2✔
51
        }
52

53
        if ($callback !== null) {
5✔
54
            foreach ($dispatches as $dispatch) {
3✔
55
                Assert::assertNotFalse($callback($dispatch), 'The callback failed.');
3✔
56
            }
57
        }
58

59
        return $this;
3✔
60
    }
61

62
    /**
63
     * Asserts that the specified `$event` has not been dispatched.
64
     */
65
    public function assertNotDispatched(string|object $event): self
3✔
66
    {
67
        $this->assertFaked();
3✔
68

69
        Assert::assertEmpty($this->findDispatches($event), 'The event was dispatched.');
3✔
70

71
        return $this;
1✔
72
    }
73

74
    /**
75
     * Asserts that the specified `$event` is being listened to.
76
     *
77
     * @param null|int $count If specified, the assertion fails if there are a different amount of listeners.
78
     */
79
    public function assertListeningTo(string $event, ?int $count = null): self
4✔
80
    {
81
        $this->assertFaked();
4✔
82

83
        Assert::assertNotEmpty(
4✔
84
            actual: $handlers = $this->findHandlersFor($event),
4✔
85
            message: 'The event is not being listened to.',
4✔
86
        );
4✔
87

88
        if ($count !== null) {
3✔
89
            Assert::assertSame($count, count($handlers), 'The number of handlers does not match.');
2✔
90
        }
91

92
        return $this;
2✔
93
    }
94

95
    private function findDispatches(string|object $event): array
9✔
96
    {
97
        return array_filter($this->fakeEventBus->dispatched, function (string|object $dispatched) use ($event) {
9✔
98
            if ($dispatched === $event) {
9✔
99
                return true;
6✔
100
            }
101

102
            if (class_exists($event) && $dispatched instanceof $event) {
6✔
103
                return true;
5✔
104
            }
105

106
            return false;
4✔
107
        });
9✔
108
    }
109

110
    /** @return array<\Tempest\EventBus\CallableEventHandler> */
111
    private function findHandlersFor(string|object $event): array
4✔
112
    {
113
        $eventName = match (true) {
4✔
114
            $event instanceof BackedEnum => $event->value,
4✔
115
            $event instanceof UnitEnum => $event->name,
4✔
116
            is_string($event) => $event,
4✔
NEW
117
            default => $event::class,
×
118
        };
4✔
119

120
        return $this->fakeEventBus->eventBusConfig->handlers[$eventName] ?? [];
4✔
121
    }
122

123
    private function assertFaked(): self
14✔
124
    {
125
        Assert::assertTrue(isset($this->fakeEventBus), 'Asserting against the event bus require the `preventEventHandling()` method to be called first.');
14✔
126

127
        return $this;
13✔
128
    }
129
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc