Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 17f68c1

Browse files
feat: Clean-up listener/subscriber after the test (#78)
Fixes #74
1 parent e01b288 commit 17f68c1

File tree

6 files changed

+148
-5
lines changed

6 files changed

+148
-5
lines changed

‎classes/MockDisablerPHPUnit10.php

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace phpmock\phpunit;
44

5+
use Closure;
56
use phpmock\Deactivatable;
67
use PHPUnit\Event\Test\Finished;
78
use PHPUnit\Event\Test\FinishedSubscriber;
@@ -22,15 +23,22 @@ class MockDisablerPHPUnit10 implements FinishedSubscriber
2223
* @var Deactivatable The function mocks.
2324
*/
2425
private $deactivatable;
26+
27+
/**
28+
* @var Closure|null The callback to execute after the test.
29+
*/
30+
private $callback;
2531

2632
/**
2733
* Sets the function mocks.
2834
*
2935
* @param Deactivatable $deactivatable The function mocks.
36+
* @param Closure|null $callback The callback to execute after the test.
3037
*/
31-
public function __construct(Deactivatable $deactivatable)
38+
public function __construct(Deactivatable $deactivatable, ?Closure$callback = null)
3239
{
3340
$this->deactivatable = $deactivatable;
41+
$this->callback = $callback;
3442
}
3543

3644
/**
@@ -39,10 +47,16 @@ public function __construct(Deactivatable $deactivatable)
3947
public function notify(Finished $event) : void
4048
{
4149
$this->deactivatable->disable();
50+
if ($this->callback !== null) {
51+
($this->callback)($this);
52+
}
4253
}
4354

4455
public function endTest(): void
4556
{
4657
$this->deactivatable->disable();
58+
if ($this->callback !== null) {
59+
($this->callback)($this);
60+
}
4761
}
4862
}

‎classes/MockDisablerPHPUnit6.php

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace phpmock\phpunit;
44

5+
use Closure;
56
use phpmock\Deactivatable;
67
use PHPUnit\Framework\BaseTestListener;
78
use PHPUnit\Framework\Test;
@@ -22,15 +23,22 @@ class MockDisablerPHPUnit6 extends BaseTestListener
2223
* @var Deactivatable The function mocks.
2324
*/
2425
private $deactivatable;
26+
27+
/**
28+
* @var Closure|null The callback to execute after the test.
29+
*/
30+
private $callback;
2531

2632
/**
2733
* Sets the function mocks.
2834
*
2935
* @param Deactivatable $deactivatable The function mocks.
36+
* @param Closure|null $callback The callback to execute after the test.
3037
*/
31-
public function __construct(Deactivatable $deactivatable)
38+
public function __construct(Deactivatable $deactivatable, Closure$callback = null)
3239
{
3340
$this->deactivatable = $deactivatable;
41+
$this->callback = $callback;
3442
}
3543

3644
/**
@@ -46,5 +54,8 @@ public function endTest(Test $test, $time)
4654
parent::endTest($test, $time);
4755

4856
$this->deactivatable->disable();
57+
if ($this->callback !== null) {
58+
($this->callback)($this);
59+
}
4960
}
5061
}

‎classes/MockDisablerPHPUnit7.php

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace phpmock\phpunit;
44

5+
use Closure;
56
use phpmock\Deactivatable;
67
use PHPUnit\Framework\BaseTestListener;
78
use PHPUnit\Framework\Test;
@@ -22,15 +23,22 @@ class MockDisablerPHPUnit7 extends BaseTestListener
2223
* @var Deactivatable The function mocks.
2324
*/
2425
private $deactivatable;
26+
27+
/**
28+
* @var Closure|null The callback to execute after the test.
29+
*/
30+
private $callback;
2531

2632
/**
2733
* Sets the function mocks.
2834
*
2935
* @param Deactivatable $deactivatable The function mocks.
36+
* @param Closure|null $callback The callback to execute after the test.
3037
*/
31-
public function __construct(Deactivatable $deactivatable)
38+
public function __construct(Deactivatable $deactivatable, Closure$callback = null)
3239
{
3340
$this->deactivatable = $deactivatable;
41+
$this->callback = $callback;
3442
}
3543

3644
/**
@@ -46,5 +54,8 @@ public function endTest(Test $test, float $time) : void
4654
parent::endTest($test, $time);
4755

4856
$this->deactivatable->disable();
57+
if ($this->callback !== null) {
58+
($this->callback)($this);
59+
}
4960
}
5061
}

‎classes/PHPMock.php

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,10 @@
77
use phpmock\MockBuilder;
88
use phpmock\Deactivatable;
99
use PHPUnit\Event\Facade;
10+
use PHPUnit\Event\Test\Finished;
1011
use PHPUnit\Framework\MockObject\MockObject;
1112
use ReflectionClass;
13+
use ReflectionMethod;
1214
use ReflectionProperty;
1315
use SebastianBergmann\Template\Template;
1416

@@ -117,8 +119,32 @@ public function registerForTearDown(Deactivatable $deactivatable)
117119
$property->setAccessible(true);
118120
$property->setValue($facade, false);
119121

122+
$method = new ReflectionMethod($facade, 'deferredDispatcher');
123+
$method->setAccessible(true);
124+
$dispatcher = $method->invoke($facade);
125+
126+
$propDispatcher = new ReflectionProperty($dispatcher, 'dispatcher');
127+
$propDispatcher->setAccessible(true);
128+
$directDispatcher = $propDispatcher->getValue($dispatcher);
129+
130+
$propSubscribers = new ReflectionProperty($directDispatcher, 'subscribers');
131+
$propSubscribers->setAccessible(true);
132+
120133
$facade->registerSubscriber(
121-
new MockDisabler($deactivatable)
134+
new MockDisabler(
135+
$deactivatable,
136+
static function (MockDisabler $original) use ($directDispatcher, $propSubscribers) {
137+
$subscribers = $propSubscribers->getValue($directDispatcher);
138+
139+
foreach ($subscribers[Finished::class] as $key => $subscriber) {
140+
if ($original === $subscriber) {
141+
unset($subscribers[Finished::class][$key]);
142+
}
143+
}
144+
145+
$propSubscribers->setValue($directDispatcher, $subscribers);
146+
}
147+
)
122148
);
123149

124150
$property->setValue($facade, true);
@@ -127,7 +153,9 @@ public function registerForTearDown(Deactivatable $deactivatable)
127153
}
128154

129155
$result = $this->getTestResultObject();
130-
$result->addListener(new MockDisabler($deactivatable));
156+
$result->addListener(new MockDisabler($deactivatable, static function (MockDisabler $listener) use ($result) {
157+
$result->removeListener($listener);
158+
}));
131159
}
132160

133161
/**

‎tests/MockDisablerTest.php

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace phpmock\phpunit;
44

5+
use phpmock\Deactivatable;
56
use phpmock\Mock;
67
use PHPUnit\Framework\TestCase;
78

@@ -32,4 +33,22 @@ public function testEndTest()
3233

3334
$this->assertEquals(1, min(1, 9));
3435
}
36+
37+
public function testCallback()
38+
{
39+
$executed = false;
40+
$executedWith = null;
41+
$mock = $this->createMock(Deactivatable::class);
42+
$disabler = new MockDisabler($mock, static function ($disabler) use (&$executed, &$executedWith) {
43+
self::assertInstanceOf(MockDisabler::class, $disabler);
44+
45+
$executed = true;
46+
$executedWith = $disabler;
47+
});
48+
49+
$disabler->endTest($this, 1);
50+
51+
self::assertTrue($executed);
52+
self::assertSame($executedWith, $disabler);
53+
}
3554
}

‎tests/PHPMockTest.php

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace phpmock\phpunit;
44

55
use phpmock\AbstractMockTestCase;
6+
use phpmock\Deactivatable;
67
use PHPUnit\Framework\ExpectationFailedException;
78

89
/**
@@ -63,4 +64,63 @@ public function testFunctionMockFailsExpectation()
6364
time(); // satisfy the expectation
6465
}
6566
}
67+
68+
/**
69+
* Register a Deactivatable for a tear down.
70+
*
71+
* @test
72+
*/
73+
public function testRegisterForTearDownRegistered()
74+
{
75+
$obj = new \stdClass();
76+
$obj->count = 0;
77+
78+
$class = new class ($obj) implements Deactivatable
79+
{
80+
private $obj;
81+
82+
public function __construct($obj)
83+
{
84+
$this->obj = $obj;
85+
}
86+
87+
public function disable()
88+
{
89+
++$this->obj->count;
90+
}
91+
};
92+
$this->registerForTearDown($class);
93+
94+
self::assertSame(0, $obj->count);
95+
96+
return $obj;
97+
}
98+
99+
/**
100+
* Check the Deactivatable was executed on a tear down of dependent test.
101+
*
102+
* @test
103+
*
104+
* @depends testRegisterForTearDownRegistered
105+
*/
106+
#[\PHPUnit\Framework\Attributes\Depends('testRegisterForTearDownRegistered')]
107+
public function testRegisterForTearDownExecuted($obj)
108+
{
109+
self::assertSame(1, $obj->count);
110+
111+
return $obj;
112+
}
113+
114+
/**
115+
* Check the Deactivatable was unregistered after executing, so it is not executed again.
116+
*
117+
* @test
118+
*
119+
* @depends testRegisterForTearDownExecuted
120+
*/
121+
#[\PHPUnit\Framework\Attributes\Depends('testRegisterForTearDownExecuted')]
122+
public function testRegisterForTearDownRemoved($obj)
123+
{
124+
self::assertSame(1, $obj->count);
125+
}
66126
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /