Skip to content

Commit 26b4810

Browse files
authored
Merge pull request #19 from chadha/DEV-RatioVoterWithNullSession
make argument session optional, with on-invalid="null"
2 parents 9ce1883 + 6553b91 commit 26b4810

3 files changed

Lines changed: 90 additions & 43 deletions

File tree

Resources/config/services.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232

3333
<!-- Ratio Voter -->
3434
<service id="ecn_featuretoggle.voter_ratio" class="Ecn\FeatureToggleBundle\Voters\RatioVoter">
35-
<argument type="service" id="session"/>
35+
<argument type="service" id="session" on-invalid="null"/>
3636
<tag name="ecn_featuretoggle.voter" alias="RatioVoter"/>
3737
</service>
3838

Tests/Voters/RatioVoterTest.php

Lines changed: 81 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,11 @@
1313
namespace Ecn\FeatureToggleBundle\Tests\Voters;
1414

1515
use Ecn\FeatureToggleBundle\Voters\RatioVoter;
16+
use InvalidArgumentException;
1617
use PHPUnit\Framework\MockObject\MockObject;
1718
use PHPUnit\Framework\TestCase;
1819
use Symfony\Component\HttpFoundation\Session\Session;
20+
use Symfony\Component\HttpFoundation\Session\SessionInterface;
1921

2022
/**
2123
* @author Pierre Groth <pierre@elbcoast.net>
@@ -32,71 +34,66 @@ public function testLowRatioVoterPass(): void
3234
$this->assertLessThan(100 - $hits, $hits);
3335
}
3436

35-
protected function getRatioVoter($ratio, $sticky = false): RatioVoter
37+
public function testStickyRatioVoterPassOnNullSession(): void
3638
{
37-
// Create service stub
38-
/** @var Session&MockObject $session */
39-
$session = $this->getMockBuilder(Session::class)
40-
->disableOriginalConstructor()
41-
->getMock();
39+
$this->expectException(InvalidArgumentException::class);
4240

43-
$session->method('get')->willReturnCallback([$this, 'getStickyCallback']);
44-
$session->method('has')->willReturnCallback([$this, 'hasStickyCallback']);
45-
46-
$params = ['ratio' => $ratio, 'sticky' => $sticky];
47-
48-
$voter = new RatioVoter($session);
49-
$voter->setFeature('ratiotest');
50-
$voter->setParams($params);
51-
52-
return $voter;
41+
$voter = $this->getRatioVoter(0.5, true, false);
42+
$voter->pass();
5343
}
5444

5545
/**
56-
* Executes the tests n time returning the number of passes
46+
* @dataProvider dataProvider
5747
*
58-
* @param RatioVoter $ratioVoter
59-
* @param int $iterationCount
60-
*
61-
* @return int
48+
* @param bool $hasSession
6249
*/
63-
private function executeTestIteration(RatioVoter $ratioVoter, $iterationCount = 100): int
50+
public function testHighRatioVoterPass(bool $hasSession): void
6451
{
65-
$hits = 0;
66-
67-
for ($i = 1; $i <= $iterationCount; $i++) {
68-
if ($ratioVoter->pass()) {
69-
$hits++;
70-
}
71-
}
72-
73-
return $hits;
74-
}
75-
76-
public function testHighRatioVoterPass(): void
77-
{
78-
$voter = $this->getRatioVoter(0.9);
52+
$voter = $this->getRatioVoter(0.9, false, $hasSession);
7953
$hits = $this->executeTestIteration($voter);
8054

8155
$this->assertGreaterThan(100 - $hits, $hits);
8256
}
8357

84-
public function testZeroRatioVoterPass(): void
58+
/**
59+
* @dataProvider dataProvider
60+
*
61+
* @param bool $hasSession
62+
*/
63+
public function testZeroRatioVoterPass(bool $hasSession): void
8564
{
86-
$voter = $this->getRatioVoter(0);
65+
$voter = $this->getRatioVoter(0, false, $hasSession);
8766
$hits = $this->executeTestIteration($voter);
8867

8968
$this->assertEquals(0, $hits);
9069
}
9170

92-
public function testOneRatioVoterPass(): void
71+
/**
72+
* @dataProvider dataProvider
73+
*
74+
* @param bool $hasSession
75+
*/
76+
public function testOneRatioVoterPass(bool $hasSession): void
9377
{
94-
$voter = $this->getRatioVoter(1);
78+
$voter = $this->getRatioVoter(1, false, $hasSession);
9579
$hits = $this->executeTestIteration($voter);
9680

9781
$this->assertEquals(100, $hits);
9882
}
9983

84+
/**
85+
* Simple data provider for $hasSession
86+
*
87+
* @return array
88+
*/
89+
public function dataProvider(): array
90+
{
91+
return [
92+
[true],
93+
[false],
94+
];
95+
}
96+
10097
public function testStickyRatioVoterPass(): void
10198
{
10299
$voter = $this->getRatioVoter(0.5, true);
@@ -135,4 +132,48 @@ public function getStickyCallback($key)
135132
{
136133
return $this->stickyValues[$key] ?? null;
137134
}
135+
136+
protected function getRatioVoter($ratio, $sticky = false, $hasSession = true): RatioVoter
137+
{
138+
$session = null;
139+
140+
if($hasSession)
141+
{
142+
// Create service stub
143+
/** @var Session&MockObject $session */
144+
$session = $this->createMock(SessionInterface::class);
145+
146+
$session->method('get')->willReturnCallback([$this, 'getStickyCallback']);
147+
$session->method('has')->willReturnCallback([$this, 'hasStickyCallback']);
148+
}
149+
150+
$params = ['ratio' => $ratio, 'sticky' => $sticky];
151+
152+
$voter = new RatioVoter($session);
153+
$voter->setFeature('ratiotest');
154+
$voter->setParams($params);
155+
156+
return $voter;
157+
}
158+
159+
/**
160+
* Executes the tests n time returning the number of passes
161+
*
162+
* @param RatioVoter $ratioVoter
163+
* @param int $iterationCount
164+
*
165+
* @return int
166+
*/
167+
private function executeTestIteration(RatioVoter $ratioVoter, $iterationCount = 100): int
168+
{
169+
$hits = 0;
170+
171+
for ($i = 1; $i <= $iterationCount; $i++) {
172+
if ($ratioVoter->pass()) {
173+
$hits++;
174+
}
175+
}
176+
177+
return $hits;
178+
}
138179
}

Voters/RatioVoter.php

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
namespace Ecn\FeatureToggleBundle\Voters;
1414

15+
use InvalidArgumentException;
1516
use Symfony\Component\HttpFoundation\Session\SessionInterface;
1617

1718
/**
@@ -37,9 +38,9 @@ class RatioVoter implements VoterInterface
3738
protected $sticky = false;
3839

3940
/**
40-
* @param SessionInterface $session
41+
* @param SessionInterface|null $session
4142
*/
42-
public function __construct(SessionInterface $session)
43+
public function __construct(SessionInterface $session = null)
4344
{
4445
$this->session = $session;
4546
}
@@ -74,7 +75,12 @@ public function pass(): bool
7475
*/
7576
protected function getStickyRatioPass(): bool
7677
{
78+
if (null === $this->session) {
79+
throw new InvalidArgumentException(sprintf('The service "%s" has a dependency on the session', get_class($this)));
80+
}
81+
7782
$sessionKey = '_ecn_featuretoggle_'.$this->feature;
83+
7884
if ($this->session->has($sessionKey)) {
7985
$pass = $this->session->get($sessionKey);
8086
} else {

0 commit comments

Comments
 (0)