Last active
January 18, 2020 18:23
-
-
Save VladaHejda/8299871 to your computer and use it in GitHub Desktop.
PHP mock ArrayAccess / Iterator / Countable. Using Phpunit with Mockery. TestCase for simple mocking classes that implements ArrayAccess, Iterator or Countable. Just create mock and call in your test: $this->mockArrayIterator($mock, $array);Notice that if you mock an interface that extends Iterator, Mockery will fail due to bug at https://github…
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
abstract class TestCase extends \PHPUnit_Framework_TestCase | |
{ | |
protected function tearDown() | |
{ | |
parent::tearDown(); | |
\Mockery::close(); | |
} | |
protected function mockArrayIterator(\Mockery\MockInterface $mock, array $items) | |
{ | |
if ($mock instanceof \ArrayAccess) { | |
foreach ($items as $key => $val) { | |
$mock->shouldReceive('offsetGet') | |
->with($key) | |
->andReturn($val); | |
$mock->shouldReceive('offsetExists') | |
->with($key) | |
->andReturn(TRUE); | |
} | |
$mock->shouldReceive('offsetExists') | |
->andReturn(FALSE); | |
} | |
if ($mock instanceof \Iterator) { | |
$counter = 0; | |
$mock->shouldReceive('rewind') | |
->andReturnUsing(function () use (& $counter) { | |
$counter = 0; | |
}); | |
$vals = array_values($items); | |
$keys = array_values(array_keys($items)); | |
$mock->shouldReceive('valid') | |
->andReturnUsing(function () use (& $counter, $vals) { | |
return isset($vals[$counter]); | |
}); | |
$mock->shouldReceive('current') | |
->andReturnUsing(function () use (& $counter, $vals) { | |
return $vals[$counter]; | |
}); | |
$mock->shouldReceive('key') | |
->andReturnUsing(function () use (& $counter, $keys) { | |
return $keys[$counter]; | |
}); | |
$mock->shouldReceive('next') | |
->andReturnUsing(function () use (& $counter) { | |
++$counter; | |
}); | |
} | |
if ($mock instanceof \Countable) { | |
$mock->shouldReceive('count') | |
->andReturn(count($items)); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* This self-tests above method. It is not required for functionality, | |
* but it would suit when someone will make improvements. | |
*/ | |
class SelfTest extends TestCase | |
{ | |
public function testMockArrayIterator() | |
{ | |
$mock = \Mockery::mock('ArrayIterator'); | |
$items = array( | |
'zero' => 3, | |
'one' => FALSE, | |
'two' => 'good job', | |
'three' => new \stdClass(), | |
'four' => array(), | |
); | |
$this->mockArrayIterator($mock, $items); | |
$this->assertTrue(isset($mock['zero'])); | |
$this->assertTrue(isset($mock['one'])); | |
$this->assertTrue(isset($mock['two'])); | |
$this->assertTrue(isset($mock['three'])); | |
$this->assertTrue(isset($mock['four'])); | |
$this->assertFalse(isset($mock['five'])); | |
$this->assertEquals(3, $mock['zero']); | |
$this->assertEquals(FALSE, $mock['one']); | |
$this->assertEquals('good job', $mock['two']); | |
$this->assertInstanceOf('stdClass', $mock['three']); | |
$this->assertEquals(array(), $mock['four']); | |
$this->assertCount(5, $mock); | |
// both cycles must pass | |
for ($n = 0; $n < 2; ++$n) { | |
$i = 0; | |
reset($items); | |
foreach ($mock as $key => $val) { | |
if ($i >= 5) { | |
$this->fail("Iterator overflow!"); | |
} | |
$this->assertEquals(key($items), $key); | |
$this->assertEquals(current($items), $val); | |
next($items); | |
++$i; | |
} | |
$this->assertEquals(5, $i); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Is this done in PHPUnit without using the Mockery class?