Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <?php declare(strict_types=1);
- namespace tests\unit;
- use BadMethodCallException;
- class Immutable extends \stdClass
- {
- private $a;
- private $b;
- private $c;
- protected $set = false;
- /**
- * Returns an instance clone that is now immutable, further calls to with<Name> wiill return clones
- *
- * @throws BadMethodCallException if already set
- * @return Immutable
- */
- public function set(): Immutable
- {
- if ($this->set) {
- throw new BadMethodCallException("Instance is already set!");
- }
- $new = clone $this;
- $new->set = true;
- return $new;
- }
- public function isHard(): bool
- {
- return $this->set;
- }
- public function withA(string $value): Immutable
- {
- $new = $this->set ? clone $this : $this;
- $new->a = $value;
- return $new;
- }
- public function withB(string $value): Immutable
- {
- $new = $this->set ? clone $this : $this;
- $new->b = $value;
- return $new;
- }
- public function withC(string $value): Immutable
- {
- $new = $this->set ? clone $this : $this;
- $new->c = $value;
- return $new;
- }
- public function __toString()
- {
- return "{$this->a} : {$this->b} : {$this->c}";
- }
- }
- class ImmutableTest extends \PHPUnit\Framework\TestCase
- {
- public function testWith()
- {
- $i = (new Immutable)->withA('a')->withB('b');
- $this->assertEquals('a : b : ', "$i");
- $i2 = $i->withC('c');
- $this->assertSame($i2, $i);
- $this->assertEquals('a : b : c', "$i");
- $this->assertEquals('a : b : c', "$i2");
- $i3 = $i2->set();
- $this->assertNotSame($i3, $i2);
- $this->assertEquals('a : b : c', "$i3");
- $i4 = $i3->withA('GG');
- $this->assertNotSame($i4, $i3);
- $this->assertEquals('GG : b : c', "$i4");
- }
- public function testUndefined()
- {
- $this->expectException(BadMethodCallException::class);
- $this->expectExceptionMessage("Instance is already set");
- $c = (new Immutable)->set()->withA('a')->set();
- }
- public function testThatDemonstrateUseCase()
- {
- // Semi builder pattern, but without needless instance generation
- $blank = (new Immutable)
- ->withA('Alpacca') // update $blank
- ->withC('Whool') // update $blank
- ->set() // $blank is from now on immutable
- ;
- $one = $blank->withB('Cool');
- $two = $blank->withB('Warm');
- $this->assertTrue($blank->isHard());
- $this->assertTrue($one->isHard());
- $this->assertTrue($two->isHard());
- $this->assertNotSame($blank, $one);
- $this->assertNotSame($blank, $two);
- $this->assertNotSame($one, $two);
- $this->assertEquals("Alpacca : : Whool", $blank);
- $this->assertEquals("Alpacca : Cool : Whool", $one);
- $this->assertEquals("Alpacca : Warm : Whool", $two);
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement