Skip to content

Commit 405f8b3

Browse files
authored
Test: Add Comprehensive Tests for EventBus (#345)
* test: Add comprehensive tests for EventBus Adds a new test suite for the EventBus, covering: - Basic subscription and unsubscription logic. - Handling of multiple subscribers and different event types. - Event and handler middleware functionality. - Behavior of the `EventSubscriptions` helper, including deinit and explicit unsubscription. * trigger ci
1 parent 2566060 commit 405f8b3

File tree

1 file changed

+252
-0
lines changed

1 file changed

+252
-0
lines changed
Lines changed: 252 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,252 @@
1+
// generated by polka.codes
2+
import Foundation
3+
import Synchronization
4+
import Testing
5+
6+
@testable import Utils
7+
8+
// TestEvent and AnotherTestEvent are defined in EventBusTests
9+
10+
// A helper actor to safely check if a handler was called and capture values
11+
private actor TestHandlerChecker<T> {
12+
private(set) var callCount = 0
13+
private(set) var capturedValues: [T] = []
14+
15+
func handlerCalled(with value: T) {
16+
callCount += 1
17+
capturedValues.append(value)
18+
}
19+
}
20+
21+
struct EventBusSubscribingTests {
22+
@Test func testBasicSubscription() async throws {
23+
let eventBus = EventBus()
24+
let handlerChecker = TestHandlerChecker<TestEvent>()
25+
26+
let testEvent = TestEvent(id: 1, value: "test")
27+
28+
let token = await eventBus.subscribe(TestEvent.self) { event in
29+
await handlerChecker.handlerCalled(with: event)
30+
}
31+
32+
await eventBus.publish(testEvent)
33+
34+
// Give some time for the event to be processed
35+
try await Task.sleep(for: .milliseconds(100))
36+
37+
let callCount = await handlerChecker.callCount
38+
#expect(callCount == 1)
39+
let capturedEvent = await handlerChecker.capturedValues.first
40+
#expect(capturedEvent?.id == testEvent.id)
41+
#expect(capturedEvent?.value == testEvent.value)
42+
43+
await eventBus.unsubscribe(token: token)
44+
}
45+
46+
@Test func testUnsubscribe() async throws {
47+
let eventBus = EventBus()
48+
let handlerChecker = TestHandlerChecker<TestEvent>()
49+
50+
let token = await eventBus.subscribe(TestEvent.self) { event in
51+
await handlerChecker.handlerCalled(with: event)
52+
}
53+
54+
await eventBus.unsubscribe(token: token)
55+
56+
await eventBus.publish(TestEvent(id: 2, value: "after unsubscribe"))
57+
58+
// Give some time for the event to be processed
59+
try await Task.sleep(for: .milliseconds(100))
60+
61+
let callCount = await handlerChecker.callCount
62+
#expect(callCount == 0)
63+
}
64+
65+
@Test func testMultipleSubscribers() async throws {
66+
let eventBus = EventBus()
67+
let handler1Checker = TestHandlerChecker<TestEvent>()
68+
let handler2Checker = TestHandlerChecker<TestEvent>()
69+
70+
let token1 = await eventBus.subscribe(TestEvent.self) { event in
71+
await handler1Checker.handlerCalled(with: event)
72+
}
73+
let token2 = await eventBus.subscribe(TestEvent.self) { event in
74+
await handler2Checker.handlerCalled(with: event)
75+
}
76+
77+
await eventBus.publish(TestEvent(id: 3, value: "multi-subscriber test"))
78+
79+
try await Task.sleep(for: .milliseconds(100))
80+
81+
let callCount1 = await handler1Checker.callCount
82+
let callCount2 = await handler2Checker.callCount
83+
#expect(callCount1 == 1)
84+
#expect(callCount2 == 1)
85+
86+
await eventBus.unsubscribe(token: token1)
87+
await eventBus.unsubscribe(token: token2)
88+
}
89+
90+
@Test func testSubscribingToDifferentEvents() async throws {
91+
let eventBus = EventBus()
92+
let testEventHandler = TestHandlerChecker<TestEvent>()
93+
let anotherTestEventHandler = TestHandlerChecker<AnotherTestEvent>()
94+
95+
let token1 = await eventBus.subscribe(TestEvent.self) { event in
96+
await testEventHandler.handlerCalled(with: event)
97+
}
98+
let token2 = await eventBus.subscribe(AnotherTestEvent.self) { event in
99+
await anotherTestEventHandler.handlerCalled(with: event)
100+
}
101+
102+
await eventBus.publish(TestEvent(id: 4, value: "first event"))
103+
await eventBus.publish(AnotherTestEvent(name: "second event"))
104+
105+
try await Task.sleep(for: .milliseconds(100))
106+
107+
let testEventCallCount = await testEventHandler.callCount
108+
let anotherEventCallCount = await anotherTestEventHandler.callCount
109+
#expect(testEventCallCount == 1)
110+
#expect(anotherEventCallCount == 1)
111+
112+
await eventBus.unsubscribe(token: token1)
113+
await eventBus.unsubscribe(token: token2)
114+
}
115+
116+
@Test func testUnsubscribeOneOfMany() async throws {
117+
let eventBus = EventBus()
118+
let handler1Checker = TestHandlerChecker<TestEvent>()
119+
let handler2Checker = TestHandlerChecker<TestEvent>()
120+
121+
let token1 = await eventBus.subscribe(TestEvent.self) { event in
122+
await handler1Checker.handlerCalled(with: event)
123+
}
124+
let token2 = await eventBus.subscribe(TestEvent.self) { event in
125+
await handler2Checker.handlerCalled(with: event)
126+
}
127+
128+
await eventBus.unsubscribe(token: token1)
129+
130+
await eventBus.publish(TestEvent(id: 5, value: "after one unsubscribe"))
131+
132+
try await Task.sleep(for: .milliseconds(100))
133+
134+
let callCount1 = await handler1Checker.callCount
135+
let callCount2 = await handler2Checker.callCount
136+
#expect(callCount1 == 0)
137+
#expect(callCount2 == 1)
138+
139+
await eventBus.unsubscribe(token: token2)
140+
}
141+
142+
// MARK: - Middleware Tests
143+
144+
private struct EventModifyingMiddleware: MiddlewareProtocol {
145+
func handle<T: Sendable>(_ event: T, next: @escaping MiddlewareHandler<T>) async throws {
146+
if let testEvent = event as? TestEvent {
147+
let modifiedEvent = TestEvent(id: testEvent.id, value: "modified")
148+
try await next(modifiedEvent as! T)
149+
} else {
150+
try await next(event)
151+
}
152+
}
153+
}
154+
155+
@Test func testEventMiddleware() async throws {
156+
let eventBus = EventBus(eventMiddleware: Middleware(EventModifyingMiddleware()))
157+
let handlerChecker = TestHandlerChecker<TestEvent>()
158+
159+
let token = await eventBus.subscribe(TestEvent.self) { event in
160+
await handlerChecker.handlerCalled(with: event)
161+
}
162+
163+
await eventBus.publish(TestEvent(id: 6, value: "original"))
164+
165+
try await Task.sleep(for: .milliseconds(100))
166+
167+
let capturedEvent = await handlerChecker.capturedValues.first
168+
#expect(capturedEvent?.value == "modified")
169+
170+
await eventBus.unsubscribe(token: token)
171+
}
172+
173+
private actor HandlerCountingMiddleware: MiddlewareProtocol {
174+
private(set) var counter = 0
175+
func handle<T: Sendable>(_ event: T, next: @escaping MiddlewareHandler<T>) async throws {
176+
counter += 1
177+
try await next(event)
178+
}
179+
}
180+
181+
@Test func testHandlerMiddleware() async throws {
182+
let countingMiddleware = HandlerCountingMiddleware()
183+
let eventBus = EventBus(handlerMiddleware: Middleware(countingMiddleware))
184+
let handler1Checker = TestHandlerChecker<TestEvent>()
185+
let handler2Checker = TestHandlerChecker<TestEvent>()
186+
187+
let token1 = await eventBus.subscribe(TestEvent.self) { event in
188+
await handler1Checker.handlerCalled(with: event)
189+
}
190+
let token2 = await eventBus.subscribe(TestEvent.self) { event in
191+
await handler2Checker.handlerCalled(with: event)
192+
}
193+
194+
await eventBus.publish(TestEvent(id: 7, value: "handler middleware test"))
195+
196+
try await Task.sleep(for: .milliseconds(100))
197+
198+
let count = await countingMiddleware.counter
199+
#expect(count == 2)
200+
let callCount1 = await handler1Checker.callCount
201+
let callCount2 = await handler2Checker.callCount
202+
#expect(callCount1 == 1)
203+
#expect(callCount2 == 1)
204+
205+
await eventBus.unsubscribe(token: token1)
206+
await eventBus.unsubscribe(token: token2)
207+
}
208+
209+
// MARK: - EventSubscriptions Helper Tests
210+
211+
@Test func testEventSubscriptionsDeinit() async throws {
212+
let eventBus = EventBus()
213+
let handlerChecker = TestHandlerChecker<TestEvent>()
214+
215+
var subscriptions: EventSubscriptions? = EventSubscriptions(eventBus: eventBus)
216+
await subscriptions!.subscribe(TestEvent.self, id: "test") { event in
217+
await handlerChecker.handlerCalled(with: event)
218+
}
219+
220+
// Deinitialize EventSubscriptions
221+
subscriptions = nil
222+
223+
// Allow time for deinit task to run
224+
try await Task.sleep(for: .milliseconds(100))
225+
226+
await eventBus.publish(TestEvent(id: 8, value: "after deinit"))
227+
228+
try await Task.sleep(for: .milliseconds(100))
229+
230+
let callCount = await handlerChecker.callCount
231+
#expect(callCount == 0)
232+
}
233+
234+
@Test func testEventSubscriptionsExplicitUnsubscribe() async throws {
235+
let eventBus = EventBus()
236+
let subscriptions = EventSubscriptions(eventBus: eventBus)
237+
let handlerChecker = TestHandlerChecker<TestEvent>()
238+
239+
let token = await subscriptions.subscribe(TestEvent.self, id: "test") { event in
240+
await handlerChecker.handlerCalled(with: event)
241+
}
242+
243+
await subscriptions.unsubscribe(token: token)
244+
245+
await eventBus.publish(TestEvent(id: 9, value: "after explicit unsubscribe"))
246+
247+
try await Task.sleep(for: .milliseconds(100))
248+
249+
let callCount = await handlerChecker.callCount
250+
#expect(callCount == 0)
251+
}
252+
}

0 commit comments

Comments
 (0)