Skip to content

Commit d9775d3

Browse files
authored
Merge pull request #98 from tarfin-labs/WB-1389-fakeable-trait-issue-event-machine
WB-1389: Fakeable trait issue - Event Machine
2 parents a3129ee + dab963b commit d9775d3

File tree

2 files changed

+149
-66
lines changed

2 files changed

+149
-66
lines changed

src/Traits/Fakeable.php

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -113,23 +113,15 @@ public static function resetAllFakes(): void
113113
*/
114114
public static function shouldRun(): Mockery\Expectation|Mockery\CompositeExpectation
115115
{
116-
if (!isset(static::$fakes[static::class])) {
117-
static::fake();
118-
}
119-
120-
return static::$fakes[static::class]->shouldReceive('__invoke');
116+
return static::fake()->shouldReceive('__invoke');
121117
}
122118

123119
/**
124120
* Set return value for the fake behavior.
125121
*/
126122
public static function shouldReturn(mixed $value): void
127123
{
128-
if (!isset(static::$fakes[static::class])) {
129-
static::fake();
130-
}
131-
132-
static::$fakes[static::class]->shouldReceive('__invoke')->andReturn($value);
124+
static::fake()->shouldReceive('__invoke')->andReturn($value);
133125
}
134126

135127
/**

tests/InvokableBehaviorFakeTest.php

Lines changed: 147 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -91,34 +91,27 @@ public function __invoke(ContextManager $context): bool
9191

9292
// region Action Behaviors
9393

94-
it('can set run expectations', function (): void {
94+
it('can set run expectations with various configurations', function (): void {
9595
// 1. Arrange
9696
$context = new ContextManager(['count' => 0]);
9797

98+
// Test basic expectation
9899
TestIncrementAction::fake();
99100
TestIncrementAction::shouldRun();
100-
101-
// 2. Act
102101
TestIncrementAction::run($context);
103-
104-
// 3. Assert
105102
TestIncrementAction::assertRan();
106-
});
107103

108-
it('works with multiple calls', function (): void {
109-
// 1. Arrange
110-
$context = new ContextManager(['count' => 0]);
104+
// Reset for next test
105+
TestIncrementAction::resetFakes();
111106

107+
// Test with multiple calls and specific configuration
112108
TestIncrementAction::fake();
113109
TestIncrementAction::shouldRun()
114110
->twice()
115111
->withAnyArgs();
116112

117-
// 2. Act
118113
TestIncrementAction::run($context);
119114
TestIncrementAction::run($context);
120-
121-
// 3. Assert
122115
TestIncrementAction::assertRan();
123116
});
124117

@@ -197,44 +190,135 @@ public function __invoke(ContextManager $context): bool
197190

198191
// endregion
199192

193+
// region Edge Cases for shouldRun and shouldReturn
194+
195+
it('handles calling shouldReturn without explicit fake call', function (): void {
196+
$context = new ContextManager(['value' => 5]);
197+
198+
// shouldReturn implicitly calls fake()
199+
TestCountGuard::shouldReturn(true);
200+
expect(TestCountGuard::isFaked())->toBeTrue();
201+
expect(TestCountGuard::run($context))->toBeTrue();
202+
});
203+
204+
it('handles calling shouldRun without explicit fake call', function (): void {
205+
$context = new ContextManager(['count' => 0]);
206+
207+
// shouldRun implicitly calls fake()
208+
TestIncrementAction::shouldRun()->once();
209+
expect(TestIncrementAction::isFaked())->toBeTrue();
210+
211+
TestIncrementAction::run($context);
212+
TestIncrementAction::assertRan();
213+
});
214+
215+
it('verifies expectation counts accurately', function (): void {
216+
TestIncrementAction::shouldRun()->times(3);
217+
218+
$context = new ContextManager();
219+
TestIncrementAction::run($context);
220+
TestIncrementAction::run($context);
221+
222+
// Should fail if we don't call it a third time
223+
expect(fn () => TestIncrementAction::getFake()->mockery_verify())
224+
->toThrow(\Mockery\Exception\InvalidCountException::class);
225+
});
226+
227+
// endregion
228+
200229
// region Guard Behavior Tests
201230

202-
it('can fake guard behavior with different return values', function (): void {
231+
it('can fake guard behavior with various return value patterns', function (): void {
203232
// 1. Arrange
204233
$context = new ContextManager(['count' => 0]);
205234

235+
// Test ordered expectations with different return values
206236
TestCountGuard::fake();
207237
TestCountGuard::shouldRun()
208238
->once()
209239
->andReturn(true)
210240
->ordered();
211241

242+
expect(TestCountGuard::run($context))->toBeTrue();
243+
212244
TestCountGuard::shouldRun()
213245
->once()
214246
->andReturn(false)
215247
->ordered();
216248

217-
// 2. Act & 3. Assert
218-
expect(TestCountGuard::run($context))->toBeTrue();
219249
expect(TestCountGuard::run($context))->toBeFalse();
220250
TestCountGuard::assertRan();
221-
});
222-
223-
it('can handle consecutive different return values', function (): void {
224-
// 1. Arrange
225-
$context = new ContextManager(['count' => 0]);
226251

252+
// Reset and test consecutive return values
253+
TestCountGuard::resetFakes();
227254
TestCountGuard::fake();
228255
TestCountGuard::shouldRun()
229256
->times(3)
230257
->andReturn(true, false, true);
231258

232-
// 2. Act & 3. Assert
233259
expect(TestCountGuard::run($context))->toBeTrue();
234260
expect(TestCountGuard::run($context))->toBeFalse();
235261
expect(TestCountGuard::run($context))->toBeTrue();
236262
});
237263

264+
it('can handle multiple shouldReturn calls in the same test', function (): void {
265+
// 1. Arrange
266+
$context = new ContextManager(['value' => 10]);
267+
268+
// 2. Act & 3. Assert - First call
269+
TestCountGuard::shouldReturn(true);
270+
expect(TestCountGuard::run($context))->toBeTrue();
271+
272+
TestCountGuard::shouldReturn(false);
273+
expect(TestCountGuard::run($context))->toBeFalse();
274+
275+
TestCountGuard::shouldReturn(true);
276+
expect(TestCountGuard::run($context))->toBeTrue();
277+
});
278+
279+
it('can mix shouldRun and shouldReturn calls in the same test', function (): void {
280+
// 1. Arrange
281+
$context = new ContextManager(['value' => 5]);
282+
283+
TestCountGuard::shouldRun()
284+
->once()
285+
->andReturn(true);
286+
expect(TestCountGuard::run($context))->toBeTrue();
287+
288+
TestCountGuard::shouldReturn(false);
289+
expect(TestCountGuard::run($context))->toBeFalse();
290+
291+
TestCountGuard::shouldRun()
292+
->once()
293+
->andReturn(true);
294+
expect(TestCountGuard::run($context))->toBeTrue();
295+
});
296+
297+
// endregion
298+
299+
// region Complex Return Types and Edge Cases
300+
301+
it('handles multiple consecutive calls with never() expectation', function (): void {
302+
TestIncrementAction::shouldRun()->never();
303+
304+
// Should not throw since we're not calling it
305+
TestIncrementAction::assertNotRan();
306+
});
307+
308+
it('can chain multiple mock configurations', function (): void {
309+
$context = new ContextManager(['count' => 5]);
310+
311+
TestIncrementAction::shouldRun()
312+
->once()
313+
->with(\Mockery::type(ContextManager::class))
314+
->andReturnUsing(function (ContextManager $ctx): void {
315+
$ctx->set('count', $ctx->get('count') * 2);
316+
});
317+
318+
TestIncrementAction::run($context);
319+
expect($context->get('count'))->toBe(10);
320+
});
321+
238322
// endregion
239323

240324
// region Behavior Isolation Tests
@@ -255,6 +339,39 @@ public function __invoke(ContextManager $context): bool
255339
TestIncrementAction::assertNotRan();
256340
});
257341

342+
it('handles multiple shouldRun calls across different behaviors', function (): void {
343+
// 1. Arrange
344+
$context = new ContextManager(['count' => 0]);
345+
346+
TestIncrementAction::shouldRun()
347+
->once()
348+
->withAnyArgs();
349+
350+
TestCountGuard::shouldReturn(false);
351+
352+
// 2. Act
353+
TestIncrementAction::run($context);
354+
expect(TestCountGuard::run($context))->toBeFalse();
355+
356+
// 3. Assert first round
357+
TestIncrementAction::assertRan();
358+
359+
// First behavior - second expectation
360+
TestIncrementAction::shouldRun()
361+
->once()
362+
->andReturnUsing(function (ContextManager $ctx): void {
363+
$ctx->set('count', 10);
364+
});
365+
366+
// Second behavior - second expectation
367+
TestCountGuard::shouldReturn(true);
368+
369+
// 4. Act again
370+
TestIncrementAction::run($context);
371+
expect(TestCountGuard::run($context))->toBeTrue();
372+
expect($context->get('count'))->toBe(10);
373+
});
374+
258375
// endregion
259376

260377
// region Exception Handling Tests
@@ -277,81 +394,55 @@ public function __invoke(ContextManager $context): bool
277394

278395
// region Reset All Fakes
279396

280-
it('can reset all fakes at once', function (): void {
397+
it('completely resets all fakes and cleans up resources', function (): void {
281398
// 1. Arrange
282399
TestIncrementAction::shouldRun()->once();
283400
TestCountGuard::shouldRun()->twice();
284401

285402
// 2. Act
286403
EventMachine::resetAllFakes();
287404

288-
// 3. Assert
405+
// 3. Assert - Verify fakes are reset
289406
expect(TestIncrementAction::isFaked())->toBeFalse()
290407
->and(TestCountGuard::isFaked())->toBeFalse()
291408
->and(TestIncrementAction::getFake())->toBeNull()
292409
->and(TestCountGuard::getFake())->toBeNull();
293-
});
294-
295-
it('removes all fake instances from container when resetting', function (): void {
296-
// 1. Arrange
297-
TestIncrementAction::shouldRun()->once();
298-
TestCountGuard::shouldRun()->once();
299-
300-
// 2. Act
301-
EventMachine::resetAllFakes();
302410

303-
// 3. Assert
411+
// Verify container cleanup
304412
expect(app()->bound(TestIncrementAction::class))->toBeFalse()
305413
->and(app()->bound(TestCountGuard::class))->toBeFalse();
306-
});
307414

308-
it('cleans mockery container when resetting fakes', function (): void {
309-
// 1. Arrange
310-
TestIncrementAction::shouldRun()->once();
311-
TestCountGuard::shouldRun()->twice();
312-
313-
// 2. Act
314-
EventMachine::resetAllFakes();
315-
316-
// 3. Assert
415+
// Verify mockery cleanup by setting new expectations
317416
TestIncrementAction::shouldRun()->never();
318-
TestIncrementAction::assertNotRan();
319-
320417
TestCountGuard::shouldRun()->never();
418+
419+
TestIncrementAction::assertNotRan();
321420
TestCountGuard::assertNotRan();
322421
});
323422

324-
it('maintains behavior isolation after resetting all fakes', function (): void {
325-
// 1. Arrange
423+
it('maintains behavior isolation and consistency after resetting fakes', function (): void {
424+
// Test isolation after reset
326425
TestIncrementAction::shouldRun()->once();
327426
TestCountGuard::shouldRun()->twice();
328427
EventMachine::resetAllFakes();
329428

330-
// 2. Act
331429
TestIncrementAction::shouldRun()->once();
332430
TestIncrementAction::run(new ContextManager(['count' => 0]));
333431

334-
// 3. Assert
335432
TestIncrementAction::assertRan();
336433
expect(TestCountGuard::isFaked())->toBeFalse();
337-
});
338434

339-
it('can reset fakes with different trait instances consistently', function (): void {
340-
// 1. Arrange
435+
// Test consistent reset with different trait instances
341436
TestIncrementAction::shouldRun()->once();
342437
TestCountGuard::shouldRun()->twice();
343438

344-
// 2. Act
345439
TestIncrementAction::resetAllFakes();
346440

347-
// Try to create new fakes
348441
TestIncrementAction::shouldRun()->once();
349442
TestCountGuard::shouldRun()->once();
350443

351-
// Reset using another instance
352444
TestCountGuard::resetAllFakes();
353445

354-
// 3. Assert
355446
expect(TestIncrementAction::isFaked())->toBeFalse()
356447
->and(TestCountGuard::isFaked())->toBeFalse()
357448
->and(TestIncrementAction::getFake())->toBeNull()

0 commit comments

Comments
 (0)