Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save VladaHejda/8299871 to your computer and use it in GitHub Desktop.
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…
<?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));
}
}
}
<?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);
}
}
}
@atayahmet
Copy link

Is this done in PHPUnit without using the Mockery class?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment