/home/mip/www/img/credit/datatables/Mockery.tar
MockingNullableMethodsTest.php000066400000011660151520664250012523 0ustar00<?php
/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mockery/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 *
 * @category   Mockery
 * @package    Mockery
 * @subpackage UnitTests
 * @copyright  Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
 */

namespace test\Mockery;

use Mockery\Adapter\Phpunit\MockeryTestCase;
use Mockery\Generator\Method;
use test\Mockery\Fixtures\MethodWithNullableReturnType;

/**
 * @requires PHP 7.1.0RC3
 */
class MockingNullableMethodsTest extends MockeryTestCase
{
    /**
     * @var \Mockery\Container
     */
    private $container;

    protected function setUp()
    {
        require_once __DIR__."/Fixtures/MethodWithNullableReturnType.php";

        $this->container = new \Mockery\Container;
    }

    protected function tearDown()
    {
        $this->container->mockery_close();
    }

    /**
     * @test
     */
    public function itShouldAllowNonNullableTypeToBeSet()
    {
        $mock = $this->container->mock('test\Mockery\Fixtures\MethodWithNullableReturnType');

        $mock->shouldReceive('nonNullablePrimitive')->andReturn('a string');
        $mock->nonNullablePrimitive();
    }

    /**
     * @test
     * @expectedException \TypeError
     */
    public function itShouldNotAllowNonNullToBeNull()
    {
        $mock = $this->container->mock('test\Mockery\Fixtures\MethodWithNullableReturnType');

        $mock->shouldReceive('nonNullablePrimitive')->andReturn(null);
        $mock->nonNullablePrimitive();
    }

    /**
     * @test
     */
    public function itShouldAllowPrimitiveNullableToBeNull()
    {
        $mock = $this->container->mock('test\Mockery\Fixtures\MethodWithNullableReturnType');

        $mock->shouldReceive('nullablePrimitive')->andReturn(null);
        $mock->nullablePrimitive();
    }

    /**
     * @test
     */
    public function itShouldAllowPrimitiveNullabeToBeSet()
    {
        $mock = $this->container->mock('test\Mockery\Fixtures\MethodWithNullableReturnType');

        $mock->shouldReceive('nullablePrimitive')->andReturn('a string');
        $mock->nullablePrimitive();
    }

    /**
     * @test
     */
    public function itShouldAllowSelfToBeSet()
    {
        $mock = $this->container->mock('test\Mockery\Fixtures\MethodWithNullableReturnType');

        $mock->shouldReceive('nonNullableSelf')->andReturn(new MethodWithNullableReturnType());
        $mock->nonNullableSelf();
    }

    /**
     * @test
     * @expectedException \TypeError
     */
    public function itShouldNotAllowSelfToBeNull()
    {
        $mock = $this->container->mock('test\Mockery\Fixtures\MethodWithNullableReturnType');

        $mock->shouldReceive('nonNullableSelf')->andReturn(null);
        $mock->nonNullableSelf();
    }

    /**
     * @test
     */
    public function itShouldAllowNullableSelfToBeSet()
    {
        $mock = $this->container->mock('test\Mockery\Fixtures\MethodWithNullableReturnType');

        $mock->shouldReceive('nullableSelf')->andReturn(new MethodWithNullableReturnType());
        $mock->nullableSelf();
    }

    /**
     * @test
     */
    public function itShouldAllowNullableSelfToBeNull()
    {
        $mock = $this->container->mock('test\Mockery\Fixtures\MethodWithNullableReturnType');

        $mock->shouldReceive('nullableSelf')->andReturn(null);
        $mock->nullableSelf();
    }

    /**
     * @test
     */
    public function itShouldAllowClassToBeSet()
    {
        $mock = $this->container->mock('test\Mockery\Fixtures\MethodWithNullableReturnType');

        $mock->shouldReceive('nonNullableClass')->andReturn(new MethodWithNullableReturnType());
        $mock->nonNullableClass();
    }

    /**
     * @test
     * @expectedException \TypeError
     */
    public function itShouldNotAllowClassToBeNull()
    {
        $mock = $this->container->mock('test\Mockery\Fixtures\MethodWithNullableReturnType');

        $mock->shouldReceive('nonNullableClass')->andReturn(null);
        $mock->nonNullableClass();
    }

    /**
     * @test
     */
    public function itShouldAllowNullalbeClassToBeSet()
    {
        $mock = $this->container->mock('test\Mockery\Fixtures\MethodWithNullableReturnType');

        $mock->shouldReceive('nullableClass')->andReturn(new MethodWithNullableReturnType());
        $mock->nullableClass();
    }

    /**
     * @test
     */
    public function itShouldAllowNullableClassToBeNull()
    {
        $mock = $this->container->mock('test\Mockery\Fixtures\MethodWithNullableReturnType');

        $mock->shouldReceive('nullableClass')->andReturn(null);
        $mock->nullableClass();
    }
}
MockingVoidMethodsTest.php000066400000002661151520664250011667 0ustar00<?php
/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mockery/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 *
 * @category   Mockery
 * @package    Mockery
 * @subpackage UnitTests
 * @copyright  Copyright (c) 2010-2014 Pádraic Brady (http://blog.astrumfutura.com)
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
 */

namespace test\Mockery;

use Mockery\Adapter\Phpunit\MockeryTestCase;

/**
 * @requires PHP 7.1.0RC3
 */
class MockingVoidMethodsTest extends MockeryTestCase
{
    public function setup()
    {
        require_once __DIR__ . '/Fixtures/VoidMethod.php';
        $this->container = new \Mockery\Container;
    }

    public function teardown()
    {
        $this->container->mockery_close();
    }

    /** @test */
    public function shouldAllowMockingVoidMethods()
    {
        $this->expectOutputString('1');

        $mock = $this->container->mock('test\Mockery\Fixtures\VoidMethod');
        $mock->shouldReceive("foo")->andReturnUsing(
            function () {
                echo 1;
            }
        );

        $mock->foo();
    }
}
RecorderTest.php000066400000013011151520664250007666 0ustar00<?php
/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mockery/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 *
 * @category   Mockery
 * @package    Mockery
 * @subpackage UnitTests
 * @copyright  Copyright (c) 2010-2014 Pádraic Brady (http://blog.astrumfutura.com)
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
 */

use Mockery\Adapter\Phpunit\MockeryTestCase;

class RecorderTest extends MockeryTestCase
{

    public function setup()
    {
        $this->container = new \Mockery\Container(\Mockery::getDefaultGenerator(), \Mockery::getDefaultLoader());
    }

    public function teardown()
    {
        $this->container->mockery_close();
    }

    public function testRecorderWithSimpleObject()
    {
        $mock = $this->container->mock(new MockeryTestSubject);
        $mock->shouldExpect(function ($subject) {
            $user = new MockeryTestSubjectUser($subject);
            $user->doFoo();
        });

        $this->assertEquals(1, $mock->foo());
        $mock->mockery_verify();
    }

    public function testArgumentsArePassedAsMethodExpectations()
    {
        $mock = $this->container->mock(new MockeryTestSubject);
        $mock->shouldExpect(function ($subject) {
            $user = new MockeryTestSubjectUser($subject);
            $user->doBar();
        });

        $this->assertEquals(4, $mock->bar(2));
        $mock->mockery_verify();
    }

    public function testArgumentsLooselyMatchedByDefault()
    {
        $mock = $this->container->mock(new MockeryTestSubject);
        $mock->shouldExpect(function ($subject) {
            $user = new MockeryTestSubjectUser($subject);
            $user->doBar();
        });

        $this->assertEquals(4, $mock->bar('2'));
        $mock->mockery_verify();
    }

    public function testMultipleMethodExpectations()
    {
        $mock = $this->container->mock(new MockeryTestSubject);
        $mock->shouldExpect(function ($subject) {
            $user = new MockeryTestSubjectUser($subject);
            $user->doFoo();
            $user->doBar();
        });

        $this->assertEquals(1, $mock->foo());
        $this->assertEquals(4, $mock->bar(2));
        $mock->mockery_verify();
    }

    public function testRecordingDoesNotSpecifyExactOrderByDefault()
    {
        $mock = $this->container->mock(new MockeryTestSubject);
        $mock->shouldExpect(function ($subject) {
            $user = new MockeryTestSubjectUser($subject);
            $user->doFoo();
            $user->doBar();
        });

        $this->assertEquals(4, $mock->bar(2));
        $this->assertEquals(1, $mock->foo());
        $mock->mockery_verify();
    }

    /**
     * @expectedException \Mockery\Exception
     */
    public function testRecordingDoesSpecifyExactOrderInStrictMode()
    {
        $mock = $this->container->mock(new MockeryTestSubject);
        $mock->shouldExpect(function ($subject) {
            $subject->shouldBeStrict();
            $user = new MockeryTestSubjectUser($subject);
            $user->doFoo();
            $user->doBar();
        });

        $mock->bar(2);
        $mock->foo();
        $mock->mockery_verify();
    }

    /**
     * @expectedException \Mockery\Exception
     */
    public function testArgumentsAreMatchedExactlyUnderStrictMode()
    {
        $mock = $this->container->mock(new MockeryTestSubject);
        $mock->shouldExpect(function ($subject) {
            $subject->shouldBeStrict();
            $user = new MockeryTestSubjectUser($subject);
            $user->doBar();
        });

        $mock->bar('2');
    }

    /**
     * @expectedException \Mockery\Exception
     */
    public function testThrowsExceptionWhenArgumentsNotExpected()
    {
        $mock = $this->container->mock(new MockeryTestSubject);
        $mock->shouldExpect(function ($subject) {
            $user = new MockeryTestSubjectUser($subject);
            $user->doBar();
        });

        $mock->bar(4);
    }

    public function testCallCountUnconstrainedByDefault()
    {
        $mock = $this->container->mock(new MockeryTestSubject);
        $mock->shouldExpect(function ($subject) {
            $user = new MockeryTestSubjectUser($subject);
            $user->doBar();
        });

        $mock->bar(2);
        $this->assertEquals(4, $mock->bar(2));
        $mock->mockery_verify();
    }

    /**
     * @expectedException \Mockery\CountValidator\Exception
     */
    public function testCallCountConstrainedInStrictMode()
    {
        $mock = $this->container->mock(new MockeryTestSubject);
        $mock->shouldExpect(function ($subject) {
            $subject->shouldBeStrict();
            $user = new MockeryTestSubjectUser($subject);
            $user->doBar();
        });

        $mock->bar(2);
        $mock->bar(2);
        $mock->mockery_verify();
    }
}

class MockeryTestSubject
{
    public function foo()
    {
        return 1;
    }
    public function bar($i)
    {
        return $i * 2;
    }
}

class MockeryTestSubjectUser
{
    public $subject = null;
    public function __construct($subject)
    {
        $this->subject = $subject;
    }
    public function doFoo()
    {
        return $this->subject->foo();
    }
    public function doBar()
    {
        return $this->subject->bar(2);
    }
}
MockClassWithFinalWakeupTest.php000066400000005001151520664250012763 0ustar00<?php
/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mockery/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 *
 * @category   Mockery
 * @package    Mockery
 * @subpackage UnitTests
 * @copyright  Copyright (c) 2012 Philip Graham <philip.robert.graham@gmail.com>
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
 */

namespace test\Mockery;

use Mockery\Adapter\Phpunit\MockeryTestCase;

class MockClassWithFinalWakeupTest extends MockeryTestCase
{

    protected function setUp()
    {
        $this->container = new \Mockery\Container;
    }

    protected function tearDown()
    {
        $this->container->mockery_close();
    }

    /**
     * @test
     *
     * Test that we are able to create partial mocks of classes that have
     * a __wakeup method marked as final. As long as __wakeup is not one of the
     * mocked methods.
     */
    public function testCreateMockForClassWithFinalWakeup()
    {
        $mock = $this->container->mock("test\Mockery\TestWithFinalWakeup");
        $this->assertInstanceOf("test\Mockery\TestWithFinalWakeup", $mock);
        $this->assertEquals('test\Mockery\TestWithFinalWakeup::__wakeup', $mock->__wakeup());

        $mock = $this->container->mock('test\Mockery\SubclassWithFinalWakeup');
        $this->assertInstanceOf('test\Mockery\SubclassWithFinalWakeup', $mock);
        $this->assertEquals('test\Mockery\TestWithFinalWakeup::__wakeup', $mock->__wakeup());
    }

    public function testCreateMockForClassWithNonFinalWakeup()
    {
        $mock = $this->container->mock('test\Mockery\TestWithNonFinalWakeup');
        $this->assertInstanceOf('test\Mockery\TestWithNonFinalWakeup', $mock);

        // Make sure __wakeup is overridden and doesn't return anything.
        $this->assertNull($mock->__wakeup());
    }
}

class TestWithFinalWakeup
{

    public function foo()
    {
        return 'foo';
    }

    public function bar()
    {
        return 'bar';
    }

    final public function __wakeup()
    {
        return __METHOD__;
    }
}

class SubclassWithFinalWakeup extends TestWithFinalWakeup
{
}

class TestWithNonFinalWakeup
{
    public function __wakeup()
    {
        return __METHOD__;
    }
}
Loader/LoaderTestCase.php000066400000001174151520664250011340 0ustar00<?php

namespace Mockery\Loader;

use Mockery\Generator\MockConfiguration;
use Mockery\Generator\MockDefinition;

abstract class LoaderTestCase extends \PHPUnit_Framework_TestCase
{
    /**
     * @test
     */
    public function loadLoadsTheCode()
    {
        $className = 'Mock_' . uniqid();
        $config = new MockConfiguration(array(), array(), array(), $className);
        $code = "<?php class $className { } ";

        $definition = new MockDefinition($config, $code);

        $this->getLoader()->load($definition);

        $this->assertTrue(class_exists($className));
    }

    abstract public function getLoader();
}
Loader/RequireLoaderTest.php000066400000000431151520664250012074 0ustar00<?php

namespace Mockery\Loader;

use Mockery as m;
use Mockery\Loader\RequireLoader;

require_once __DIR__.'/LoaderTestCase.php';

class RequireLoaderTest extends LoaderTestCase
{
    public function getLoader()
    {
        return new RequireLoader(sys_get_temp_dir());
    }
}
Loader/EvalLoaderTest.php000066400000000376151520664250011357 0ustar00<?php

namespace Mockery\Loader;

use Mockery as m;
use Mockery\Loader\EvalLoader;

require_once __DIR__.'/LoaderTestCase.php';

class EvalLoaderTest extends LoaderTestCase
{
    public function getLoader()
    {
        return new EvalLoader();
    }
}
MockTest.php000066400000013650151520664250007023 0ustar00<?php
/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mockery/blob/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 *
 * @category   Mockery
 * @package    Mockery
 * @subpackage UnitTests
 * @copyright  Copyright (c) 2010-2014 Pádraic Brady (http://blog.astrumfutura.com)
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
 */

use Mockery\Adapter\Phpunit\MockeryTestCase;

class Mockery_MockTest extends MockeryTestCase
{
    /**
     * @var \Mockery\Container
     */
    public $container;

    public function setup()
    {
        $this->container = new \Mockery\Container(\Mockery::getDefaultGenerator(), \Mockery::getDefaultLoader());
    }

    public function teardown()
    {
        $this->container->mockery_close();
    }

    public function testAnonymousMockWorksWithNotAllowingMockingOfNonExistentMethods()
    {
        \Mockery::getConfiguration()->allowMockingNonExistentMethods(false);
        $m = $this->container->mock();
        $m->shouldReceive("test123")->andReturn(true);
        assertThat($m->test123(), equalTo(true));
        \Mockery::getConfiguration()->allowMockingNonExistentMethods(true);
    }

    public function testMockWithNotAllowingMockingOfNonExistentMethodsCanBeGivenAdditionalMethodsToMockEvenIfTheyDontExistOnClass()
    {
        \Mockery::getConfiguration()->allowMockingNonExistentMethods(false);
        $m = $this->container->mock('ExampleClassForTestingNonExistentMethod');
        $m->shouldAllowMockingMethod('testSomeNonExistentMethod');
        $m->shouldReceive("testSomeNonExistentMethod")->andReturn(true);
        assertThat($m->testSomeNonExistentMethod(), equalTo(true));
        \Mockery::getConfiguration()->allowMockingNonExistentMethods(true);
    }

    public function testShouldAllowMockingMethodReturnsMockInstance()
    {
        $m = Mockery::mock('someClass');
        $this->assertInstanceOf('Mockery\MockInterface', $m->shouldAllowMockingMethod('testFunction'));
    }

    public function testShouldAllowMockingProtectedMethodReturnsMockInstance()
    {
        $m = Mockery::mock('someClass');
        $this->assertInstanceOf('Mockery\MockInterface', $m->shouldAllowMockingProtectedMethods('testFunction'));
    }

    public function testMockAddsToString()
    {
        $mock = $this->container->mock('ClassWithNoToString');
        assertThat(hasToString($mock));
    }

    public function testMockToStringMayBeDeferred()
    {
        $mock = $this->container->mock('ClassWithToString')->shouldDeferMissing();
        assertThat((string)$mock, equalTo("foo"));
    }

    public function testMockToStringShouldIgnoreMissingAlwaysReturnsString()
    {
        $mock = $this->container->mock('ClassWithNoToString')->shouldIgnoreMissing();
        assertThat(isNonEmptyString((string)$mock));

        $mock->asUndefined();
        assertThat(isNonEmptyString((string)$mock));
    }

    public function testShouldIgnoreMissing()
    {
        $mock = $this->container->mock('ClassWithNoToString')->shouldIgnoreMissing();
        assertThat(nullValue($mock->nonExistingMethod()));
    }

    public function testShouldIgnoreDebugInfo()
    {
        $mock = $this->container->mock('ClassWithDebugInfo');

        $mock->__debugInfo();
    }

    /**
     * @expectedException Mockery\Exception
     */
    public function testShouldIgnoreMissingDisallowMockingNonExistentMethodsUsingGlobalConfiguration()
    {
        Mockery::getConfiguration()->allowMockingNonExistentMethods(false);
        $mock = $this->container->mock('ClassWithMethods')->shouldIgnoreMissing();
        $mock->shouldReceive('nonExistentMethod');
    }

    /**
     * @expectedException BadMethodCallException
     */
    public function testShouldIgnoreMissingCallingNonExistentMethodsUsingGlobalConfiguration()
    {
        Mockery::getConfiguration()->allowMockingNonExistentMethods(false);
        $mock = $this->container->mock('ClassWithMethods')->shouldIgnoreMissing();
        $mock->nonExistentMethod();
    }

    public function testShouldIgnoreMissingCallingExistentMethods()
    {
        Mockery::getConfiguration()->allowMockingNonExistentMethods(false);
        $mock = $this->container->mock('ClassWithMethods')->shouldIgnoreMissing();
        assertThat(nullValue($mock->foo()));
        $mock->shouldReceive('bar')->passthru();
        assertThat($mock->bar(), equalTo('bar'));
    }

    public function testShouldIgnoreMissingCallingNonExistentMethods()
    {
        Mockery::getConfiguration()->allowMockingNonExistentMethods(true);
        $mock = $this->container->mock('ClassWithMethods')->shouldIgnoreMissing();
        assertThat(nullValue($mock->foo()));
        assertThat(nullValue($mock->bar()));
        assertThat(nullValue($mock->nonExistentMethod()));

        $mock->shouldReceive(array('foo' => 'new_foo', 'nonExistentMethod' => 'result'));
        $mock->shouldReceive('bar')->passthru();
        assertThat($mock->foo(), equalTo('new_foo'));
        assertThat($mock->bar(), equalTo('bar'));
        assertThat($mock->nonExistentMethod(), equalTo('result'));
    }

    public function testCanMockException()
    {
        $exception = Mockery::mock('Exception');
        $this->assertInstanceOf('Exception', $exception);
    }
}


class ExampleClassForTestingNonExistentMethod
{
}

class ClassWithToString
{
    public function __toString()
    {
        return 'foo';
    }
}

class ClassWithNoToString
{
}

class ClassWithMethods
{
    public function foo()
    {
        return 'foo';
    }

    public function bar()
    {
        return 'bar';
    }
}

class ClassWithDebugInfo
{
    public function __debugInfo()
    {
        return array('test' => 'test');
    }
}
MockingInternalModuleClassWithOptionalParameterByReferenceTest.php000066400000004221151520664250021661 0ustar00<?php

/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mockery/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 */

namespace test\Mockery;

use Mockery\Adapter\Phpunit\MockeryTestCase;

class MockingInternalModuleClassWithOptionalParameterByReferenceTest extends MockeryTestCase
{
    protected function setUp()
    {
        if (!extension_loaded('memcache')) {
            $this->markTestSkipped('ext/memcache not installed');
        }
        parent::setUp();
    }

    protected function tearDown()
    {
        static::closeMockery();
        parent::tearDown();
    }

    /**
     * Regression for {@see https://github.com/mockery/mockery/issues/757 issue#757}
     *
     * @test
     */
    public function mockingInternalModuleClassWithOptionalParameterByReferenceMayNotBreakCodeGeneration()
    {
        // this works for macOS
        \Mockery::getConfiguration()
            ->setInternalClassMethodParamMap('Memcache', 'get', array('$id', '&$flags = null'));
        // strange thing is, the reflected class under linux is MemcachePool not Memcache
        \Mockery::getConfiguration()
            ->setInternalClassMethodParamMap('MemcachePool', 'get', array('$id', '&$flags = null'));
        $memcache = \Mockery::mock('Memcache');
        $memcache->shouldReceive('get')
            ->with(
                $id = 'foobar',
                \Mockery::on(
                    function (&$flags) {
                        $valid = null === $flags;
                        $flags = 255;
                        return $valid;
                    }
                )
            )
            ->once()
            ->andReturn($expected = time());
        $paramFlags = null;
        $this->assertSame($expected, $memcache->get($id, $paramFlags));
        \Mockery::close();
        $this->assertSame(255, $paramFlags);
    }
}
ContainerTest.php000066400000145463151520664250010064 0ustar00<?php
/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mockery/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 *
 * @category   Mockery
 * @package    Mockery
 * @subpackage UnitTests
 * @copyright  Copyright (c) 2010-2014 Pádraic Brady (http://blog.astrumfutura.com)
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
 */

use Mockery\Generator\MockConfigurationBuilder;
use Mockery\Adapter\Phpunit\MockeryTestCase;

class ContainerTest extends MockeryTestCase
{

    /** @var Mockery\Container */
    private $container;

    public function setup()
    {
        $this->container = new Mockery\Container(Mockery::getDefaultGenerator(), new Mockery\Loader\EvalLoader());
    }

    public function teardown()
    {
        $this->container->mockery_close();
    }

    public function testSimplestMockCreation()
    {
        $m = $this->container->mock();
        $m->shouldReceive('foo')->andReturn('bar');
        $this->assertEquals('bar', $m->foo());
    }

    public function testGetKeyOfDemeterMockShouldReturnKeyWhenMatchingMock()
    {
        $m = $this->container->mock();
        $m->shouldReceive('foo->bar');
        $this->assertRegExp(
            '/Mockery_(\d+)__demeter_foo/',
            $this->container->getKeyOfDemeterMockFor('foo')
        );
    }
    public function testGetKeyOfDemeterMockShouldReturnNullWhenNoMatchingMock()
    {
        $method = 'unknownMethod';
        $this->assertNull($this->container->getKeyOfDemeterMockFor($method));

        $m = $this->container->mock();
        $m->shouldReceive('method');
        $this->assertNull($this->container->getKeyOfDemeterMockFor($method));

        $m->shouldReceive('foo->bar');
        $this->assertNull($this->container->getKeyOfDemeterMockFor($method));
    }


    public function testNamedMocksAddNameToExceptions()
    {
        $m = $this->container->mock('Foo');
        $m->shouldReceive('foo')->with(1)->andReturn('bar');
        try {
            $m->foo();
        } catch (\Mockery\Exception $e) {
            $this->assertTrue((bool) preg_match("/Foo/", $e->getMessage()));
        }
    }

    public function testSimpleMockWithArrayDefs()
    {
        $m = $this->container->mock(array('foo'=>1, 'bar'=>2));
        $this->assertEquals(1, $m->foo());
        $this->assertEquals(2, $m->bar());
    }

    public function testSimpleMockWithArrayDefsCanBeOverridden()
    {
        // eg. In shared test setup
        $m = $this->container->mock(array('foo' => 1, 'bar' => 2));

        // and then overridden in one test
        $m->shouldReceive('foo')->with('baz')->once()->andReturn(2);
        $m->shouldReceive('bar')->with('baz')->once()->andReturn(42);

        $this->assertEquals(2, $m->foo('baz'));
        $this->assertEquals(42, $m->bar('baz'));
    }

    public function testNamedMockWithArrayDefs()
    {
        $m = $this->container->mock('Foo', array('foo'=>1, 'bar'=>2));
        $this->assertEquals(1, $m->foo());
        $this->assertEquals(2, $m->bar());
        try {
            $m->f();
        } catch (BadMethodCallException $e) {
            $this->assertTrue((bool) preg_match("/Foo/", $e->getMessage()));
        }
    }

    public function testNamedMockWithArrayDefsCanBeOverridden()
    {
        // eg. In shared test setup
        $m = $this->container->mock('Foo', array('foo' => 1));

        // and then overridden in one test
        $m->shouldReceive('foo')->with('bar')->once()->andReturn(2);

        $this->assertEquals(2, $m->foo('bar'));

        try {
            $m->f();
        } catch (BadMethodCallException $e) {
            $this->assertTrue((bool) preg_match("/Foo/", $e->getMessage()));
        }
    }

    public function testNamedMockMultipleInterfaces()
    {
        $m = $this->container->mock('stdClass, ArrayAccess, Countable', array('foo'=>1, 'bar'=>2));
        $this->assertEquals(1, $m->foo());
        $this->assertEquals(2, $m->bar());
        try {
            $m->f();
        } catch (BadMethodCallException $e) {
            $this->assertTrue((bool) preg_match("/stdClass/", $e->getMessage()));
            $this->assertTrue((bool) preg_match("/ArrayAccess/", $e->getMessage()));
            $this->assertTrue((bool) preg_match("/Countable/", $e->getMessage()));
        }
    }

    public function testNamedMockWithConstructorArgs()
    {
        $m = $this->container->mock("MockeryTest_ClassConstructor2[foo]", array($param1 = new stdClass()));
        $m->shouldReceive("foo")->andReturn(123);
        $this->assertEquals(123, $m->foo());
        $this->assertEquals($param1, $m->getParam1());
    }

    public function testNamedMockWithConstructorArgsAndArrayDefs()
    {
        $m = $this->container->mock(
            "MockeryTest_ClassConstructor2[foo]",
            array($param1 = new stdClass()),
            array("foo" => 123)
        );
        $this->assertEquals(123, $m->foo());
        $this->assertEquals($param1, $m->getParam1());
    }

    public function testNamedMockWithConstructorArgsWithInternalCallToMockedMethod()
    {
        $m = $this->container->mock("MockeryTest_ClassConstructor2[foo]", array($param1 = new stdClass()));
        $m->shouldReceive("foo")->andReturn(123);
        $this->assertEquals(123, $m->bar());
    }

    public function testNamedMockWithConstructorArgsButNoQuickDefsShouldLeaveConstructorIntact()
    {
        $m = $this->container->mock("MockeryTest_ClassConstructor2", array($param1 = new stdClass()));
        $m->shouldDeferMissing();
        $this->assertEquals($param1, $m->getParam1());
    }

    public function testNamedMockWithShouldDeferMissing()
    {
        $m = $this->container->mock("MockeryTest_ClassConstructor2", array($param1 = new stdClass()));
        $m->shouldDeferMissing();
        $this->assertEquals('foo', $m->bar());
        $m->shouldReceive("bar")->andReturn(123);
        $this->assertEquals(123, $m->bar());
    }

    /**
     * @expectedException BadMethodCallException
     */
    public function testNamedMockWithShouldDeferMissingThrowsIfNotAvailable()
    {
        $m = $this->container->mock("MockeryTest_ClassConstructor2", array($param1 = new stdClass()));
        $m->shouldDeferMissing();
        $m->foorbar123();
    }

    public function testMockingAKnownConcreteClassSoMockInheritsClassType()
    {
        $m = $this->container->mock('stdClass');
        $m->shouldReceive('foo')->andReturn('bar');
        $this->assertEquals('bar', $m->foo());
        $this->assertTrue($m instanceof stdClass);
    }

    public function testMockingAKnownUserClassSoMockInheritsClassType()
    {
        $m = $this->container->mock('MockeryTest_TestInheritedType');
        $this->assertTrue($m instanceof MockeryTest_TestInheritedType);
    }

    public function testMockingAConcreteObjectCreatesAPartialWithoutError()
    {
        $m = $this->container->mock(new stdClass);
        $m->shouldReceive('foo')->andReturn('bar');
        $this->assertEquals('bar', $m->foo());
        $this->assertTrue($m instanceof stdClass);
    }

    public function testCreatingAPartialAllowsDynamicExpectationsAndPassesThroughUnexpectedMethods()
    {
        $m = $this->container->mock(new MockeryTestFoo);
        $m->shouldReceive('bar')->andReturn('bar');
        $this->assertEquals('bar', $m->bar());
        $this->assertEquals('foo', $m->foo());
        $this->assertTrue($m instanceof MockeryTestFoo);
    }

    public function testCreatingAPartialAllowsExpectationsToInterceptCallsToImplementedMethods()
    {
        $m = $this->container->mock(new MockeryTestFoo2);
        $m->shouldReceive('bar')->andReturn('baz');
        $this->assertEquals('baz', $m->bar());
        $this->assertEquals('foo', $m->foo());
        $this->assertTrue($m instanceof MockeryTestFoo2);
    }

    public function testBlockForwardingToPartialObject()
    {
        $m = $this->container->mock(new MockeryTestBar1, array('foo'=>1, Mockery\Container::BLOCKS => array('method1')));
        $this->assertSame($m, $m->method1());
    }

    public function testPartialWithArrayDefs()
    {
        $m = $this->container->mock(new MockeryTestBar1, array('foo'=>1, Mockery\Container::BLOCKS => array('method1')));
        $this->assertEquals(1, $m->foo());
    }

    public function testPassingClosureAsFinalParameterUsedToDefineExpectations()
    {
        $m = $this->container->mock('foo', function ($m) {
            $m->shouldReceive('foo')->once()->andReturn('bar');
        });
        $this->assertEquals('bar', $m->foo());
    }

    /**
     * @expectedException \Mockery\Exception
     */
    public function testMockingAKnownConcreteFinalClassThrowsErrors_OnlyPartialMocksCanMockFinalElements()
    {
        $m = $this->container->mock('MockeryFoo3');
    }

    public function testMockingAKnownConcreteClassWithFinalMethodsThrowsNoException()
    {
        $m = $this->container->mock('MockeryFoo4');
    }

    /**
     * @group finalclass
     */
    public function testFinalClassesCanBePartialMocks()
    {
        $m = $this->container->mock(new MockeryFoo3);
        $m->shouldReceive('foo')->andReturn('baz');
        $this->assertEquals('baz', $m->foo());
        $this->assertFalse($m instanceof MockeryFoo3);
    }

    public function testSplClassWithFinalMethodsCanBeMocked()
    {
        $m = $this->container->mock('SplFileInfo');
        $m->shouldReceive('foo')->andReturn('baz');
        $this->assertEquals('baz', $m->foo());
        $this->assertTrue($m instanceof SplFileInfo);
    }

    public function testSplClassWithFinalMethodsCanBeMockedMultipleTimes()
    {
        $this->container->mock('SplFileInfo');
        $m = $this->container->mock('SplFileInfo');
        $m->shouldReceive('foo')->andReturn('baz');
        $this->assertEquals('baz', $m->foo());
        $this->assertTrue($m instanceof SplFileInfo);
    }

    public function testClassesWithFinalMethodsCanBeProxyPartialMocks()
    {
        $m = $this->container->mock(new MockeryFoo4);
        $m->shouldReceive('foo')->andReturn('baz');
        $this->assertEquals('baz', $m->foo());
        $this->assertEquals('bar', $m->bar());
        $this->assertTrue($m instanceof MockeryFoo4);
    }

    public function testClassesWithFinalMethodsCanBeProperPartialMocks()
    {
        $m = $this->container->mock('MockeryFoo4[bar]');
        $m->shouldReceive('bar')->andReturn('baz');
        $this->assertEquals('baz', $m->foo());
        $this->assertEquals('baz', $m->bar());
        $this->assertTrue($m instanceof MockeryFoo4);
    }

    public function testClassesWithFinalMethodsCanBeProperPartialMocksButFinalMethodsNotPartialed()
    {
        $m = $this->container->mock('MockeryFoo4[foo]');
        $m->shouldReceive('foo')->andReturn('foo');
        $this->assertEquals('baz', $m->foo()); // partial expectation ignored - will fail callcount assertion
        $this->assertTrue($m instanceof MockeryFoo4);
    }

    public function testSplfileinfoClassMockPassesUserExpectations()
    {
        $file = $this->container->mock('SplFileInfo[getFilename,getPathname,getExtension,getMTime]', array(__FILE__));
        $file->shouldReceive('getFilename')->once()->andReturn('foo');
        $file->shouldReceive('getPathname')->once()->andReturn('path/to/foo');
        $file->shouldReceive('getExtension')->once()->andReturn('css');
        $file->shouldReceive('getMTime')->once()->andReturn(time());
    }

    public function testCanMockInterface()
    {
        $m = $this->container->mock('MockeryTest_Interface');
        $this->assertTrue($m instanceof MockeryTest_Interface);
    }

    public function testCanMockSpl()
    {
        $m = $this->container->mock('\\SplFixedArray');
        $this->assertTrue($m instanceof SplFixedArray);
    }

    public function testCanMockInterfaceWithAbstractMethod()
    {
        $m = $this->container->mock('MockeryTest_InterfaceWithAbstractMethod');
        $this->assertTrue($m instanceof MockeryTest_InterfaceWithAbstractMethod);
        $m->shouldReceive('foo')->andReturn(1);
        $this->assertEquals(1, $m->foo());
    }

    public function testCanMockAbstractWithAbstractProtectedMethod()
    {
        $m = $this->container->mock('MockeryTest_AbstractWithAbstractMethod');
        $this->assertTrue($m instanceof MockeryTest_AbstractWithAbstractMethod);
    }

    public function testCanMockInterfaceWithPublicStaticMethod()
    {
        $m = $this->container->mock('MockeryTest_InterfaceWithPublicStaticMethod');
        $this->assertTrue($m instanceof MockeryTest_InterfaceWithPublicStaticMethod);
    }

    public function testCanMockClassWithConstructor()
    {
        $m = $this->container->mock('MockeryTest_ClassConstructor');
        $this->assertTrue($m instanceof MockeryTest_ClassConstructor);
    }

    public function testCanMockClassWithConstructorNeedingClassArgs()
    {
        $m = $this->container->mock('MockeryTest_ClassConstructor2');
        $this->assertTrue($m instanceof MockeryTest_ClassConstructor2);
    }

    /**
     * @group partial
     */
    public function testCanPartiallyMockANormalClass()
    {
        $m = $this->container->mock('MockeryTest_PartialNormalClass[foo]');
        $this->assertTrue($m instanceof MockeryTest_PartialNormalClass);
        $m->shouldReceive('foo')->andReturn('cba');
        $this->assertEquals('abc', $m->bar());
        $this->assertEquals('cba', $m->foo());
    }

    /**
     * @group partial
     */
    public function testCanPartiallyMockAnAbstractClass()
    {
        $m = $this->container->mock('MockeryTest_PartialAbstractClass[foo]');
        $this->assertTrue($m instanceof MockeryTest_PartialAbstractClass);
        $m->shouldReceive('foo')->andReturn('cba');
        $this->assertEquals('abc', $m->bar());
        $this->assertEquals('cba', $m->foo());
    }

    /**
     * @group partial
     */
    public function testCanPartiallyMockANormalClassWith2Methods()
    {
        $m = $this->container->mock('MockeryTest_PartialNormalClass2[foo, baz]');
        $this->assertTrue($m instanceof MockeryTest_PartialNormalClass2);
        $m->shouldReceive('foo')->andReturn('cba');
        $m->shouldReceive('baz')->andReturn('cba');
        $this->assertEquals('abc', $m->bar());
        $this->assertEquals('cba', $m->foo());
        $this->assertEquals('cba', $m->baz());
    }

    /**
     * @group partial
     */
    public function testCanPartiallyMockAnAbstractClassWith2Methods()
    {
        $m = $this->container->mock('MockeryTest_PartialAbstractClass2[foo,baz]');
        $this->assertTrue($m instanceof MockeryTest_PartialAbstractClass2);
        $m->shouldReceive('foo')->andReturn('cba');
        $m->shouldReceive('baz')->andReturn('cba');
        $this->assertEquals('abc', $m->bar());
        $this->assertEquals('cba', $m->foo());
        $this->assertEquals('cba', $m->baz());
    }

    /**
     * @expectedException \Mockery\Exception
     * @group partial
     */
    public function testThrowsExceptionIfSettingExpectationForNonMockedMethodOfPartialMock()
    {
        $this->markTestSkipped('For now...');
        $m = $this->container->mock('MockeryTest_PartialNormalClass[foo]');
        $this->assertTrue($m instanceof MockeryTest_PartialNormalClass);
        $m->shouldReceive('bar')->andReturn('cba');
    }

    /**
     * @expectedException \Mockery\Exception
     * @group partial
     */
    public function testThrowsExceptionIfClassOrInterfaceForPartialMockDoesNotExist()
    {
        $m = $this->container->mock('MockeryTest_PartialNormalClassXYZ[foo]');
    }

    /**
     * @group issue/4
     */
    public function testCanMockClassContainingMagicCallMethod()
    {
        $m = $this->container->mock('MockeryTest_Call1');
        $this->assertTrue($m instanceof MockeryTest_Call1);
    }

    /**
     * @group issue/4
     */
    public function testCanMockClassContainingMagicCallMethodWithoutTypeHinting()
    {
        $m = $this->container->mock('MockeryTest_Call2');
        $this->assertTrue($m instanceof MockeryTest_Call2);
    }

    /**
     * @group issue/14
     */
    public function testCanMockClassContainingAPublicWakeupMethod()
    {
        $m = $this->container->mock('MockeryTest_Wakeup1');
        $this->assertTrue($m instanceof MockeryTest_Wakeup1);
    }

    /**
     * @group issue/18
     */
    public function testCanMockClassUsingMagicCallMethodsInPlaceOfNormalMethods()
    {
        $m = Mockery::mock('Gateway');
        $m->shouldReceive('iDoSomethingReallyCoolHere');
        $m->iDoSomethingReallyCoolHere();
    }

    /**
     * @group issue/18
     */
    public function testCanPartialMockObjectUsingMagicCallMethodsInPlaceOfNormalMethods()
    {
        $m = Mockery::mock(new Gateway);
        $m->shouldReceive('iDoSomethingReallyCoolHere');
        $m->iDoSomethingReallyCoolHere();
    }

    /**
     * @group issue/13
     */
    public function testCanMockClassWhereMethodHasReferencedParameter()
    {
        $m = Mockery::mock(new MockeryTest_MethodParamRef);
    }

    /**
     * @group issue/13
     */
    public function testCanPartiallyMockObjectWhereMethodHasReferencedParameter()
    {
        $m = Mockery::mock(new MockeryTest_MethodParamRef2);
    }

    /**
     * @group issue/11
     */
    public function testMockingAKnownConcreteClassCanBeGrantedAnArbitraryClassType()
    {
        $m = $this->container->mock('alias:MyNamespace\MyClass');
        $m->shouldReceive('foo')->andReturn('bar');
        $this->assertEquals('bar', $m->foo());
        $this->assertTrue($m instanceof MyNamespace\MyClass);
    }

    /**
     * @group issue/15
     */
    public function testCanMockMultipleInterfaces()
    {
        $m = $this->container->mock('MockeryTest_Interface1, MockeryTest_Interface2');
        $this->assertTrue($m instanceof MockeryTest_Interface1);
        $this->assertTrue($m instanceof MockeryTest_Interface2);
    }

    /**
     * @expectedException \Mockery\Exception
     */
    public function testMockingMultipleInterfacesThrowsExceptionWhenGivenNonExistingClassOrInterface()
    {
        $m = $this->container->mock('DoesNotExist, MockeryTest_Interface2');
        $this->assertTrue($m instanceof MockeryTest_Interface1);
        $this->assertTrue($m instanceof MockeryTest_Interface2);
    }

    /**
     * @group issue/15
     */
    public function testCanMockClassAndApplyMultipleInterfaces()
    {
        $m = $this->container->mock('MockeryTestFoo, MockeryTest_Interface1, MockeryTest_Interface2');
        $this->assertTrue($m instanceof MockeryTestFoo);
        $this->assertTrue($m instanceof MockeryTest_Interface1);
        $this->assertTrue($m instanceof MockeryTest_Interface2);
    }

    /**
     * @group issue/7
     *
     * Noted: We could complicate internally, but a blind class is better built
     * with a real class noted up front (stdClass is a perfect choice it is
     * behaviourless). Fine, it's a muddle - but we need to draw a line somewhere.
     */
    public function testCanMockStaticMethods()
    {
        Mockery::setContainer($this->container);
        $m = $this->container->mock('alias:MyNamespace\MyClass2');
        $m->shouldReceive('staticFoo')->andReturn('bar');
        $this->assertEquals('bar', \MyNameSpace\MyClass2::staticFoo());
        Mockery::resetContainer();
    }

    /**
     * @group issue/7
     * @expectedException \Mockery\CountValidator\Exception
     */
    public function testMockedStaticMethodsObeyMethodCounting()
    {
        Mockery::setContainer($this->container);
        $m = $this->container->mock('alias:MyNamespace\MyClass3');
        $m->shouldReceive('staticFoo')->once()->andReturn('bar');
        $this->container->mockery_verify();
        Mockery::resetContainer();
    }

    /**
     * @expectedException BadMethodCallException
     */
    public function testMockedStaticThrowsExceptionWhenMethodDoesNotExist()
    {
        Mockery::setContainer($this->container);
        $m = $this->container->mock('alias:MyNamespace\StaticNoMethod');
        $this->assertEquals('bar', MyNameSpace\StaticNoMethod::staticFoo());
        Mockery::resetContainer();
    }

    /**
     * @group issue/17
     */
    public function testMockingAllowsPublicPropertyStubbingOnRealClass()
    {
        $m = $this->container->mock('MockeryTestFoo');
        $m->foo = 'bar';
        $this->assertEquals('bar', $m->foo);
        //$this->assertTrue(array_key_exists('foo', $m->mockery_getMockableProperties()));
    }

    /**
     * @group issue/17
     */
    public function testMockingAllowsPublicPropertyStubbingOnNamedMock()
    {
        $m = $this->container->mock('Foo');
        $m->foo = 'bar';
        $this->assertEquals('bar', $m->foo);
        //$this->assertTrue(array_key_exists('foo', $m->mockery_getMockableProperties()));
    }

    /**
     * @group issue/17
     */
    public function testMockingAllowsPublicPropertyStubbingOnPartials()
    {
        $m = $this->container->mock(new stdClass);
        $m->foo = 'bar';
        $this->assertEquals('bar', $m->foo);
        //$this->assertTrue(array_key_exists('foo', $m->mockery_getMockableProperties()));
    }

    /**
     * @group issue/17
     */
    public function testMockingDoesNotStubNonStubbedPropertiesOnPartials()
    {
        $m = $this->container->mock(new MockeryTest_ExistingProperty);
        $this->assertEquals('bar', $m->foo);
        $this->assertFalse(array_key_exists('foo', $m->mockery_getMockableProperties()));
    }

    public function testCreationOfInstanceMock()
    {
        $m = $this->container->mock('overload:MyNamespace\MyClass4');
        $this->assertTrue($m instanceof MyNamespace\MyClass4);
    }

    public function testInstantiationOfInstanceMock()
    {
        Mockery::setContainer($this->container);
        $m = $this->container->mock('overload:MyNamespace\MyClass5');
        $instance = new MyNamespace\MyClass5;
        $this->assertTrue($instance instanceof MyNamespace\MyClass5);
        Mockery::resetContainer();
    }

    public function testInstantiationOfInstanceMockImportsExpectations()
    {
        Mockery::setContainer($this->container);
        $m = $this->container->mock('overload:MyNamespace\MyClass6');
        $m->shouldReceive('foo')->andReturn('bar');
        $instance = new MyNamespace\MyClass6;
        $this->assertEquals('bar', $instance->foo());
        Mockery::resetContainer();
    }

    public function testInstantiationOfInstanceMocksIgnoresVerificationOfOriginMock()
    {
        Mockery::setContainer($this->container);
        $m = $this->container->mock('overload:MyNamespace\MyClass7');
        $m->shouldReceive('foo')->once()->andReturn('bar');
        $this->container->mockery_verify();
        Mockery::resetContainer(); //should not throw an exception
    }

    /**
     * @expectedException \Mockery\CountValidator\Exception
     */
    public function testInstantiationOfInstanceMocksAddsThemToContainerForVerification()
    {
        Mockery::setContainer($this->container);
        $m = $this->container->mock('overload:MyNamespace\MyClass8');
        $m->shouldReceive('foo')->once();
        $instance = new MyNamespace\MyClass8;
        $this->container->mockery_verify();
        Mockery::resetContainer();
    }

    public function testInstantiationOfInstanceMocksDoesNotHaveCountValidatorCrossover()
    {
        Mockery::setContainer($this->container);
        $m = $this->container->mock('overload:MyNamespace\MyClass9');
        $m->shouldReceive('foo')->once();
        $instance1 = new MyNamespace\MyClass9;
        $instance2 = new MyNamespace\MyClass9;
        $instance1->foo();
        $instance2->foo();
        $this->container->mockery_verify();
        Mockery::resetContainer();
    }

    /**
     * @expectedException \Mockery\CountValidator\Exception
     */
    public function testInstantiationOfInstanceMocksDoesNotHaveCountValidatorCrossover2()
    {
        Mockery::setContainer($this->container);
        $m = $this->container->mock('overload:MyNamespace\MyClass10');
        $m->shouldReceive('foo')->once();
        $instance1 = new MyNamespace\MyClass10;
        $instance2 = new MyNamespace\MyClass10;
        $instance1->foo();
        $this->container->mockery_verify();
        Mockery::resetContainer();
    }

    public function testCreationOfInstanceMockWithFullyQualifiedName()
    {
        $m = $this->container->mock('overload:\MyNamespace\MyClass11');
        $this->assertTrue($m instanceof MyNamespace\MyClass11);
    }

    public function testInstanceMocksShouldIgnoreMissing()
    {
        Mockery::setContainer($this->container);
        $m = $this->container->mock('overload:MyNamespace\MyClass12');
        $m->shouldIgnoreMissing();

        $instance = new MyNamespace\MyClass12();
        $instance->foo();

        Mockery::resetContainer();
    }

    /**
     * @group issue/451
     */
    public function testSettingPropertyOnInstanceMockWillSetItOnActualInstance()
    {
        Mockery::setContainer($this->container);
        $m = $this->container->mock('overload:MyNamespace\MyClass13');
        $m->shouldReceive('foo')->andSet('bar', 'baz');
        $instance = new MyNamespace\MyClass13;
        $instance->foo();
        $this->assertEquals('baz', $m->bar);
        $this->assertEquals('baz', $instance->bar);
        Mockery::resetContainer();
    }

    public function testMethodParamsPassedByReferenceHaveReferencePreserved()
    {
        $m = $this->container->mock('MockeryTestRef1');
        $m->shouldReceive('foo')->with(
            Mockery::on(function (&$a) {
                $a += 1;
                return true;
            }),
            Mockery::any()
        );
        $a = 1;
        $b = 1;
        $m->foo($a, $b);
        $this->assertEquals(2, $a);
        $this->assertEquals(1, $b);
    }

    /**
     * Meant to test the same logic as
     * testCanOverrideExpectedParametersOfExtensionPHPClassesToPreserveRefs,
     * but:
     * - doesn't require an extension
     * - isn't actually known to be used
     */
    public function testCanOverrideExpectedParametersOfInternalPHPClassesToPreserveRefs()
    {
        Mockery::getConfiguration()->setInternalClassMethodParamMap(
            'DateTime', 'modify', array('&$string')
        );
        // @ used to avoid E_STRICT for incompatible signature
        @$m = $this->container->mock('DateTime');
        $this->assertInstanceOf("Mockery\MockInterface", $m, "Mocking failed, remove @ error suppresion to debug");
        $m->shouldReceive('modify')->with(
            Mockery::on(function (&$string) {
                $string = 'foo';
                return true;
            })
        );
        $data ='bar';
        $m->modify($data);
        $this->assertEquals('foo', $data);
        $this->container->mockery_verify();
        Mockery::resetContainer();
        Mockery::getConfiguration()->resetInternalClassMethodParamMaps();
    }

    /**
     * Real world version of
     * testCanOverrideExpectedParametersOfInternalPHPClassesToPreserveRefs
     */
    public function testCanOverrideExpectedParametersOfExtensionPHPClassesToPreserveRefs()
    {
        if (!class_exists('MongoCollection', false)) {
            $this->markTestSkipped('ext/mongo not installed');
        }
        Mockery::getConfiguration()->setInternalClassMethodParamMap(
            'MongoCollection', 'insert', array('&$data', '$options')
        );
        // @ used to avoid E_STRICT for incompatible signature
        @$m = $this->container->mock('MongoCollection');
        $this->assertInstanceOf("Mockery\MockInterface", $m, "Mocking failed, remove @ error suppresion to debug");
        $m->shouldReceive('insert')->with(
            Mockery::on(function (&$data) {
                $data['_id'] = 123;
                return true;
            }),
            Mockery::type('array')
        );
        $data = array('a'=>1,'b'=>2);
        $m->insert($data, array());
        $this->assertTrue(isset($data['_id']));
        $this->assertEquals(123, $data['_id']);
        $this->container->mockery_verify();
        Mockery::resetContainer();
        Mockery::getConfiguration()->resetInternalClassMethodParamMaps();
    }

    public function testCanCreateNonOverridenInstanceOfPreviouslyOverridenInternalClasses()
    {
        Mockery::getConfiguration()->setInternalClassMethodParamMap(
            'DateTime', 'modify', array('&$string')
        );
        // @ used to avoid E_STRICT for incompatible signature
        @$m = $this->container->mock('DateTime');
        $this->assertInstanceOf("Mockery\MockInterface", $m, "Mocking failed, remove @ error suppresion to debug");
        $rc = new ReflectionClass($m);
        $rm = $rc->getMethod('modify');
        $params = $rm->getParameters();
        $this->assertTrue($params[0]->isPassedByReference());

        Mockery::getConfiguration()->resetInternalClassMethodParamMaps();

        $m = $this->container->mock('DateTime');
        $this->assertInstanceOf("Mockery\MockInterface", $m, "Mocking failed");
        $rc = new ReflectionClass($m);
        $rm = $rc->getMethod('modify');
        $params = $rm->getParameters();
        $this->assertFalse($params[0]->isPassedByReference());

        Mockery::resetContainer();
        Mockery::getConfiguration()->resetInternalClassMethodParamMaps();
    }

    /**
     * @group abstract
     */
    public function testCanMockAbstractClassWithAbstractPublicMethod()
    {
        $m = $this->container->mock('MockeryTest_AbstractWithAbstractPublicMethod');
        $this->assertTrue($m instanceof MockeryTest_AbstractWithAbstractPublicMethod);
    }

    /**
     * @issue issue/21
     */
    public function testClassDeclaringIssetDoesNotThrowException()
    {
        Mockery::setContainer($this->container);
        $m = $this->container->mock('MockeryTest_IssetMethod');
        $this->container->mockery_verify();
        Mockery::resetContainer();
    }

    /**
     * @issue issue/21
     */
    public function testClassDeclaringUnsetDoesNotThrowException()
    {
        Mockery::setContainer($this->container);
        $m = $this->container->mock('MockeryTest_UnsetMethod');
        $this->container->mockery_verify();
        Mockery::resetContainer();
    }

    /**
     * @issue issue/35
     */
    public function testCallingSelfOnlyReturnsLastMockCreatedOrCurrentMockBeingProgrammedSinceTheyAreOneAndTheSame()
    {
        Mockery::setContainer($this->container);
        $m = $this->container->mock('MockeryTestFoo');
        $this->assertFalse($this->container->self() instanceof MockeryTestFoo2);
        //$m = $this->container->mock('MockeryTestFoo2');
        //$this->assertTrue($this->container->self() instanceof MockeryTestFoo2);
        //$m = $this->container->mock('MockeryTestFoo');
        //$this->assertFalse(Mockery::self() instanceof MockeryTestFoo2);
        //$this->assertTrue(Mockery::self() instanceof MockeryTestFoo);
        Mockery::resetContainer();
    }

    /**
     * @issue issue/89
     */
    public function testCreatingMockOfClassWithExistingToStringMethodDoesntCreateClassWithTwoToStringMethods()
    {
        Mockery::setContainer($this->container);
        $m = $this->container->mock('MockeryTest_WithToString'); // this would fatal
        $m->shouldReceive("__toString")->andReturn('dave');
        $this->assertEquals("dave", "$m");
    }

    public function testGetExpectationCount_freshContainer()
    {
        $this->assertEquals(0, $this->container->mockery_getExpectationCount());
    }

    public function testGetExpectationCount_simplestMock()
    {
        $m = $this->container->mock();
        $m->shouldReceive('foo')->andReturn('bar');
        $this->assertEquals(1, $this->container->mockery_getExpectationCount());
    }

    public function testMethodsReturningParamsByReferenceDoesNotErrorOut()
    {
        $this->container->mock('MockeryTest_ReturnByRef');
        $mock = $this->container->mock('MockeryTest_ReturnByRef');
        $mock->shouldReceive("get")->andReturn($var = 123);
        $this->assertSame($var, $mock->get());
    }

    public function testMockCallableTypeHint()
    {
        if (PHP_VERSION_ID >= 50400) {
            $this->container->mock('MockeryTest_MockCallableTypeHint');
        }
    }

    public function testCanMockClassWithReservedWordMethod()
    {
        if (!extension_loaded("redis")) {
            $this->markTestSkipped("phpredis not installed");
        }

        $this->container->mock("Redis");
    }

    public function testUndeclaredClassIsDeclared()
    {
        $this->assertFalse(class_exists("BlahBlah"));
        $mock = $this->container->mock("BlahBlah");
        $this->assertInstanceOf("BlahBlah", $mock);
    }

    public function testUndeclaredClassWithNamespaceIsDeclared()
    {
        $this->assertFalse(class_exists("MyClasses\Blah\BlahBlah"));
        $mock = $this->container->mock("MyClasses\Blah\BlahBlah");
        $this->assertInstanceOf("MyClasses\Blah\BlahBlah", $mock);
    }

    public function testUndeclaredClassWithNamespaceIncludingLeadingOperatorIsDeclared()
    {
        $this->assertFalse(class_exists("\MyClasses\DaveBlah\BlahBlah"));
        $mock = $this->container->mock("\MyClasses\DaveBlah\BlahBlah");
        $this->assertInstanceOf("\MyClasses\DaveBlah\BlahBlah", $mock);
    }

    public function testMockingPhpredisExtensionClassWorks()
    {
        if (!class_exists('Redis')) {
            $this->markTestSkipped('PHPRedis extension required for this test');
        }
        $m = $this->container->mock('Redis');
    }

    public function testIssetMappingUsingProxiedPartials_CheckNoExceptionThrown()
    {
        $var = $this->container->mock(new MockeryTestIsset_Bar());
        $mock = $this->container->mock(new MockeryTestIsset_Foo($var));
        $mock->shouldReceive('bar')->once();
        $mock->bar();
        $this->container->mockery_teardown(); // closed by teardown()
    }

    /**
     * @group traversable1
     */
    public function testCanMockInterfacesExtendingTraversable()
    {
        $mock = $this->container->mock('MockeryTest_InterfaceWithTraversable');
        $this->assertInstanceOf('MockeryTest_InterfaceWithTraversable', $mock);
        $this->assertInstanceOf('ArrayAccess', $mock);
        $this->assertInstanceOf('Countable', $mock);
        $this->assertInstanceOf('Traversable', $mock);
    }

    /**
     * @group traversable2
     */
    public function testCanMockInterfacesAlongsideTraversable()
    {
        $mock = $this->container->mock('stdClass, ArrayAccess, Countable, Traversable');
        $this->assertInstanceOf('stdClass', $mock);
        $this->assertInstanceOf('ArrayAccess', $mock);
        $this->assertInstanceOf('Countable', $mock);
        $this->assertInstanceOf('Traversable', $mock);
    }

    public function testInterfacesCanHaveAssertions()
    {
        Mockery::setContainer($this->container);
        $m = $this->container->mock('stdClass, ArrayAccess, Countable, Traversable');
        $m->shouldReceive('foo')->once();
        $m->foo();
        $this->container->mockery_verify();
        Mockery::resetContainer();
    }

    public function testMockingIteratorAggregateDoesNotImplementIterator()
    {
        $mock = $this->container->mock('MockeryTest_ImplementsIteratorAggregate');
        $this->assertInstanceOf('IteratorAggregate', $mock);
        $this->assertInstanceOf('Traversable', $mock);
        $this->assertNotInstanceOf('Iterator', $mock);
    }

    public function testMockingInterfaceThatExtendsIteratorDoesNotImplementIterator()
    {
        $mock = $this->container->mock('MockeryTest_InterfaceThatExtendsIterator');
        $this->assertInstanceOf('Iterator', $mock);
        $this->assertInstanceOf('Traversable', $mock);
    }

    public function testMockingInterfaceThatExtendsIteratorAggregateDoesNotImplementIterator()
    {
        $mock = $this->container->mock('MockeryTest_InterfaceThatExtendsIteratorAggregate');
        $this->assertInstanceOf('IteratorAggregate', $mock);
        $this->assertInstanceOf('Traversable', $mock);
        $this->assertNotInstanceOf('Iterator', $mock);
    }

    public function testMockingIteratorAggregateDoesNotImplementIteratorAlongside()
    {
        $mock = $this->container->mock('IteratorAggregate');
        $this->assertInstanceOf('IteratorAggregate', $mock);
        $this->assertInstanceOf('Traversable', $mock);
        $this->assertNotInstanceOf('Iterator', $mock);
    }

    public function testMockingIteratorDoesNotImplementIteratorAlongside()
    {
        $mock = $this->container->mock('Iterator');
        $this->assertInstanceOf('Iterator', $mock);
        $this->assertInstanceOf('Traversable', $mock);
    }

    public function testMockingIteratorDoesNotImplementIterator()
    {
        $mock = $this->container->mock('MockeryTest_ImplementsIterator');
        $this->assertInstanceOf('Iterator', $mock);
        $this->assertInstanceOf('Traversable', $mock);
    }

    public function testMockeryCloseForIllegalIssetFileInclude()
    {
        $m = Mockery::mock('StdClass')
            ->shouldReceive('get')
            ->andReturn(false)
            ->getMock();
        $m->get();
        Mockery::close();
    }

    public function testMockeryShouldDistinguishBetweenConstructorParamsAndClosures()
    {
        $obj = new MockeryTestFoo();
        $mock = $this->container->mock('MockeryTest_ClassMultipleConstructorParams[dave]',
            array( &$obj, 'foo' ));
    }

    /** @group nette */
    public function testMockeryShouldNotMockCallstaticMagicMethod()
    {
        $mock = $this->container->mock('MockeryTest_CallStatic');
    }

    /**
     * @issue issue/139
     */
    public function testCanMockClassWithOldStyleConstructorAndArguments()
    {
        $mock = $this->container->mock('MockeryTest_OldStyleConstructor');
    }

    /** @group issue/144 */
    public function testMockeryShouldInterpretEmptyArrayAsConstructorArgs()
    {
        $mock = $this->container->mock("EmptyConstructorTest", array());
        $this->assertSame(0, $mock->numberOfConstructorArgs);
    }

    /** @group issue/144 */
    public function testMockeryShouldCallConstructorByDefaultWhenRequestingPartials()
    {
        $mock = $this->container->mock("EmptyConstructorTest[foo]");
        $this->assertSame(0, $mock->numberOfConstructorArgs);
    }

    /** @group issue/158 */
    public function testMockeryShouldRespectInterfaceWithMethodParamSelf()
    {
        $this->container->mock('MockeryTest_InterfaceWithMethodParamSelf');
    }

    /** @group issue/162 */
    public function testMockeryDoesntTryAndMockLowercaseToString()
    {
        $this->container->mock('MockeryTest_Lowercase_ToString');
    }

    /** @group issue/175 */
    public function testExistingStaticMethodMocking()
    {
        Mockery::setContainer($this->container);
        $mock = $this->container->mock('MockeryTest_PartialStatic[mockMe]');

        $mock->shouldReceive('mockMe')->with(5)->andReturn(10);

        $this->assertEquals(10, $mock::mockMe(5));
        $this->assertEquals(3, $mock::keepMe(3));
    }

    /**
     * @group issue/154
     * @expectedException InvalidArgumentException
     * @expectedExceptionMessage protectedMethod() cannot be mocked as it a protected method and mocking protected methods is not allowed for this mock
     */
    public function testShouldThrowIfAttemptingToStubProtectedMethod()
    {
        $mock = $this->container->mock('MockeryTest_WithProtectedAndPrivate');
        $mock->shouldReceive("protectedMethod");
    }

    /**
     * @group issue/154
     * @expectedException InvalidArgumentException
     * @expectedExceptionMessage privateMethod() cannot be mocked as it is a private method
     */
    public function testShouldThrowIfAttemptingToStubPrivateMethod()
    {
        $mock = $this->container->mock('MockeryTest_WithProtectedAndPrivate');
        $mock->shouldReceive("privateMethod");
    }

    public function testWakeupMagicIsNotMockedToAllowSerialisationInstanceHack()
    {
        $mock = $this->container->mock('DateTime');
    }

    /**
     * @group issue/154
     */
    public function testCanMockMethodsWithRequiredParamsThatHaveDefaultValues()
    {
        $mock = $this->container->mock('MockeryTest_MethodWithRequiredParamWithDefaultValue');
        $mock->shouldIgnoreMissing();
        $mock->foo(null, 123);
    }

    /**
     * @test
     * @group issue/294
     * @expectedException Mockery\Exception\RuntimeException
     * @expectedExceptionMessage Could not load mock DateTime, class already exists
     */
    public function testThrowsWhenNamedMockClassExistsAndIsNotMockery()
    {
        $builder = new MockConfigurationBuilder();
        $builder->setName("DateTime");
        $mock = $this->container->mock($builder);
    }

    /**
     * @expectedException Mockery\Exception\NoMatchingExpectationException
     * @expectedExceptionMessage MyTestClass::foo(resource(...))
     */
    public function testHandlesMethodWithArgumentExpectationWhenCalledWithResource()
    {
        $mock = $this->container->mock('MyTestClass');
        $mock->shouldReceive('foo')->with(array('yourself' => 21));

        $mock->foo(fopen('php://memory', 'r'));
    }

    /**
     * @expectedException Mockery\Exception\NoMatchingExpectationException
     * @expectedExceptionMessage MyTestClass::foo(array('myself'=>'array(...)',))
     */
    public function testHandlesMethodWithArgumentExpectationWhenCalledWithCircularArray()
    {
        $testArray = array();
        $testArray['myself'] =& $testArray;

        $mock = $this->container->mock('MyTestClass');
        $mock->shouldReceive('foo')->with(array('yourself' => 21));

        $mock->foo($testArray);
    }

    /**
     * @expectedException Mockery\Exception\NoMatchingExpectationException
     * @expectedExceptionMessage MyTestClass::foo(array('a_scalar'=>2,'an_array'=>'array(...)',))
     */
    public function testHandlesMethodWithArgumentExpectationWhenCalledWithNestedArray()
    {
        $testArray = array();
        $testArray['a_scalar'] = 2;
        $testArray['an_array'] = array(1, 2, 3);

        $mock = $this->container->mock('MyTestClass');
        $mock->shouldReceive('foo')->with(array('yourself' => 21));

        $mock->foo($testArray);
    }

    /**
     * @expectedException Mockery\Exception\NoMatchingExpectationException
     * @expectedExceptionMessage MyTestClass::foo(array('a_scalar'=>2,'an_object'=>'object(stdClass)',))
     */
    public function testHandlesMethodWithArgumentExpectationWhenCalledWithNestedObject()
    {
        $testArray = array();
        $testArray['a_scalar'] = 2;
        $testArray['an_object'] = new stdClass();

        $mock = $this->container->mock('MyTestClass');
        $mock->shouldReceive('foo')->with(array('yourself' => 21));

        $mock->foo($testArray);
    }

    /**
     * @expectedException Mockery\Exception\NoMatchingExpectationException
     * @expectedExceptionMessage MyTestClass::foo(array('a_scalar'=>2,'a_closure'=>'object(Closure
     */
    public function testHandlesMethodWithArgumentExpectationWhenCalledWithNestedClosure()
    {
        $testArray = array();
        $testArray['a_scalar'] = 2;
        $testArray['a_closure'] = function () {
        };

        $mock = $this->container->mock('MyTestClass');
        $mock->shouldReceive('foo')->with(array('yourself' => 21));

        $mock->foo($testArray);
    }

    /**
     * @expectedException Mockery\Exception\NoMatchingExpectationException
     * @expectedExceptionMessage MyTestClass::foo(array('a_scalar'=>2,'a_resource'=>'resource(...)',))
     */
    public function testHandlesMethodWithArgumentExpectationWhenCalledWithNestedResource()
    {
        $testArray = array();
        $testArray['a_scalar'] = 2;
        $testArray['a_resource'] = fopen('php://memory', 'r');

        $mock = $this->container->mock('MyTestClass');
        $mock->shouldReceive('foo')->with(array('yourself' => 21));

        $mock->foo($testArray);
    }

    /**
     * @test
     * @group issue/339
     */
    public function canMockClassesThatDescendFromInternalClasses()
    {
        $mock = $this->container->mock("MockeryTest_ClassThatDescendsFromInternalClass");
        $this->assertInstanceOf("DateTime", $mock);
    }

    /**
     * @test
     * @group issue/339
     */
    public function canMockClassesThatImplementSerializable()
    {
        $mock = $this->container->mock("MockeryTest_ClassThatImplementsSerializable");
        $this->assertInstanceOf("Serializable", $mock);
    }

    /**
     * @test
     * @group issue/346
     */
    public function canMockInternalClassesThatImplementSerializable()
    {
        $mock = $this->container->mock("ArrayObject");
        $this->assertInstanceOf("Serializable", $mock);
    }
}

class MockeryTest_CallStatic
{
    public static function __callStatic($method, $args)
    {
    }
}

class MockeryTest_ClassMultipleConstructorParams
{
    public function __construct($a, $b)
    {
    }

    public function dave()
    {
    }
}

interface MockeryTest_InterfaceWithTraversable extends ArrayAccess, Traversable, Countable
{
    public function self();
}

class MockeryTestIsset_Bar
{
    public function doSomething()
    {
    }
}

class MockeryTestIsset_Foo
{
    private $var;

    public function __construct($var)
    {
        $this->var = $var;
    }

    public function __get($name)
    {
        $this->var->doSomething();
    }

    public function __isset($name)
    {
        return (bool) strlen($this->__get($name));
    }
}

class MockeryTest_IssetMethod
{
    protected $_properties = array();

    public function __construct()
    {
    }

    public function __isset($property)
    {
        return isset($this->_properties[$property]);
    }
}

class MockeryTest_UnsetMethod
{
    protected $_properties = array();

    public function __construct()
    {
    }

    public function __unset($property)
    {
        unset($this->_properties[$property]);
    }
}

class MockeryTestFoo
{
    public function foo()
    {
        return 'foo';
    }
}

class MockeryTestFoo2
{
    public function foo()
    {
        return 'foo';
    }

    public function bar()
    {
        return 'bar';
    }
}

final class MockeryFoo3
{
    public function foo()
    {
        return 'baz';
    }
}

class MockeryFoo4
{
    final public function foo()
    {
        return 'baz';
    }

    public function bar()
    {
        return 'bar';
    }
}

interface MockeryTest_Interface
{
}
interface MockeryTest_Interface1
{
}
interface MockeryTest_Interface2
{
}

interface MockeryTest_InterfaceWithAbstractMethod
{
    public function set();
}

interface MockeryTest_InterfaceWithPublicStaticMethod
{
    public static function self();
}

abstract class MockeryTest_AbstractWithAbstractMethod
{
    abstract protected function set();
}

class MockeryTest_WithProtectedAndPrivate
{
    protected function protectedMethod()
    {
    }

    private function privateMethod()
    {
    }
}

class MockeryTest_ClassConstructor
{
    public function __construct($param1)
    {
    }
}

class MockeryTest_ClassConstructor2
{
    protected $param1;

    public function __construct(stdClass $param1)
    {
        $this->param1 = $param1;
    }

    public function getParam1()
    {
        return $this->param1;
    }

    public function foo()
    {
        return 'foo';
    }

    public function bar()
    {
        return $this->foo();
    }
}

class MockeryTest_Call1
{
    public function __call($method, array $params)
    {
    }
}

class MockeryTest_Call2
{
    public function __call($method, $params)
    {
    }
}

class MockeryTest_Wakeup1
{
    public function __construct()
    {
    }

    public function __wakeup()
    {
    }
}

class MockeryTest_ExistingProperty
{
    public $foo = 'bar';
}

abstract class MockeryTest_AbstractWithAbstractPublicMethod
{
    abstract public function foo($a, $b);
}

// issue/18
class SoCool
{
    public function iDoSomethingReallyCoolHere()
    {
        return 3;
    }
}

class Gateway
{
    public function __call($method, $args)
    {
        $m = new SoCool();
        return call_user_func_array(array($m, $method), $args);
    }
}

class MockeryTestBar1
{
    public function method1()
    {
        return $this;
    }
}

class MockeryTest_ReturnByRef
{
    public $i = 0;

    public function &get()
    {
        return $this->$i;
    }
}

class MockeryTest_MethodParamRef
{
    public function method1(&$foo)
    {
        return true;
    }
}
class MockeryTest_MethodParamRef2
{
    public function method1(&$foo)
    {
        return true;
    }
}
class MockeryTestRef1
{
    public function foo(&$a, $b)
    {
    }
}

class MockeryTest_PartialNormalClass
{
    public function foo()
    {
        return 'abc';
    }

    public function bar()
    {
        return 'abc';
    }
}

abstract class MockeryTest_PartialAbstractClass
{
    abstract public function foo();

    public function bar()
    {
        return 'abc';
    }
}

class MockeryTest_PartialNormalClass2
{
    public function foo()
    {
        return 'abc';
    }

    public function bar()
    {
        return 'abc';
    }

    public function baz()
    {
        return 'abc';
    }
}

abstract class MockeryTest_PartialAbstractClass2
{
    abstract public function foo();

    public function bar()
    {
        return 'abc';
    }

    abstract public function baz();
}

class MockeryTest_TestInheritedType
{
}

if (PHP_VERSION_ID >= 50400) {
    class MockeryTest_MockCallableTypeHint
    {
        public function foo(callable $baz)
        {
            $baz();
        }

        public function bar(callable $callback = null)
        {
            $callback();
        }
    }
}

class MockeryTest_WithToString
{
    public function __toString()
    {
    }
}

class MockeryTest_ImplementsIteratorAggregate implements IteratorAggregate
{
    public function getIterator()
    {
        return new ArrayIterator(array());
    }
}

class MockeryTest_ImplementsIterator implements Iterator
{
    public function rewind()
    {
    }

    public function current()
    {
    }

    public function key()
    {
    }

    public function next()
    {
    }

    public function valid()
    {
    }
}

class MockeryTest_OldStyleConstructor
{
    public function MockeryTest_OldStyleConstructor($arg)
    {
    }
}

class EmptyConstructorTest
{
    public $numberOfConstructorArgs;

    public function __construct()
    {
        $this->numberOfConstructorArgs = count(func_get_args());
    }

    public function foo()
    {
    }
}

interface MockeryTest_InterfaceWithMethodParamSelf
{
    public function foo(self $bar);
}

class MockeryTest_Lowercase_ToString
{
    public function __tostring()
    {
    }
}

class MockeryTest_PartialStatic
{
    public static function mockMe($a)
    {
        return $a;
    }

    public static function keepMe($b)
    {
        return $b;
    }
}

class MockeryTest_MethodWithRequiredParamWithDefaultValue
{
    public function foo(DateTime $bar = null, $baz)
    {
    }
}

interface MockeryTest_InterfaceThatExtendsIterator extends Iterator
{
    public function foo();
}

interface MockeryTest_InterfaceThatExtendsIteratorAggregate extends IteratorAggregate
{
    public function foo();
}

class MockeryTest_ClassThatDescendsFromInternalClass extends DateTime
{
}

class MockeryTest_ClassThatImplementsSerializable implements Serializable
{
    public function serialize()
    {
    }

    public function unserialize($serialized)
    {
    }
}
Test/Generator/MockConfigurationBuilderTest.php000066400000002073151520664250015724 0ustar00<?php

namespace Mockery\Generator;

use Mockery as m;
use Mockery\Generator\MockConfigurationBuilder;

class MockConfigurationBuilderTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @test
     */
    public function reservedWordsAreBlackListedByDefault()
    {
        $builder = new MockConfigurationBuilder;
        $this->assertContains('abstract', $builder->getMockConfiguration()->getBlackListedMethods());

        // need a builtin for this
        $this->markTestSkipped("Need a builtin class with a method that is a reserved word");
    }

    /**
     * @test
     */
    public function magicMethodsAreBlackListedByDefault()
    {
        $builder = new MockConfigurationBuilder;
        $builder->addTarget("Mockery\Generator\ClassWithMagicCall");
        $methods = $builder->getMockConfiguration()->getMethodsToMock();
        $this->assertEquals(1, count($methods));
        $this->assertEquals("foo", $methods[0]->getName());
    }
}

class ClassWithMagicCall
{
    public function foo()
    {
    }
    public function __call($method, $args)
    {
    }
}
NamedMockTest.php000066400000003267151520664250007773 0ustar00<?php
/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mockery/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 *
 * @category   Mockery
 * @package    Mockery
 * @subpackage UnitTests
 * @copyright  Copyright (c) 2010-2014 Pádraic Brady (http://blog.astrumfutura.com)
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
 */

use Mockery\Adapter\Phpunit\MockeryTestCase;

class NamedMockTest extends MockeryTestCase
{
    /** @test */
    public function itCreatesANamedMock()
    {
        $mock = Mockery::namedMock("Mockery\Dave123");
        $this->assertEquals("Mockery\Dave123", get_class($mock));
    }

    /** @test */
    public function itCreatesPassesFurtherArgumentsJustLikeMock()
    {
        $mock = Mockery::namedMock("Mockery\Dave456", "DateTimeZone", array(
            "getDave" => "dave"
        ));

        $this->assertInstanceOf("DateTimeZone", $mock);
        $this->assertEquals("dave", $mock->getDave());
    }

    /**
     * @test
     * @expectedException Mockery\Exception
     * @expectedExceptionMessage The mock named 'Mockery\Dave7' has been already defined with a different mock configuration
     */
    public function itShouldThrowIfAttemptingToRedefineNamedMock()
    {
        $mock = Mockery::namedMock("Mockery\Dave7");
        $mock = Mockery::namedMock("Mockery\Dave7", "DateTime");
    }
}
MockingProtectedMethodsTest.php000066400000007010151520664250012710 0ustar00<?php
/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mockery/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 *
 * @category   Mockery
 * @package    Mockery
 * @subpackage UnitTests
 * @copyright  Copyright (c) 2010-2014 Pádraic Brady (http://blog.astrumfutura.com)
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
 */

namespace test\Mockery;

use Mockery\Adapter\Phpunit\MockeryTestCase;

class MockingProtectedMethodsTest extends MockeryTestCase
{

    public function setup()
    {
        $this->container = new \Mockery\Container;
    }

    public function teardown()
    {
        $this->container->mockery_close();
    }

    /**
     * @test
     *
     * This is a regression test, basically we don't want the mock handling
     * interfering with calling protected methods partials
     */
    public function shouldAutomaticallyDeferCallsToProtectedMethodsForPartials()
    {
        $mock = $this->container->mock("test\Mockery\TestWithProtectedMethods[foo]");
        $this->assertEquals("bar", $mock->bar());
    }

    /**
     * @test
     *
     * This is a regression test, basically we don't want the mock handling
     * interfering with calling protected methods partials
     */
    public function shouldAutomaticallyDeferCallsToProtectedMethodsForRuntimePartials()
    {
        $mock = $this->container->mock("test\Mockery\TestWithProtectedMethods")->shouldDeferMissing();
        $this->assertEquals("bar", $mock->bar());
    }

    /** @test */
    public function shouldAutomaticallyIgnoreAbstractProtectedMethods()
    {
        $mock = $this->container->mock("test\Mockery\TestWithProtectedMethods")->shouldDeferMissing();
        $this->assertEquals(null, $mock->foo());
    }

    /** @test */
    public function shouldAllowMockingProtectedMethods()
    {
        $mock = $this->container->mock("test\Mockery\TestWithProtectedMethods")
            ->shouldDeferMissing()
            ->shouldAllowMockingProtectedMethods();

        $mock->shouldReceive("protectedBar")->andReturn("notbar");
        $this->assertEquals("notbar", $mock->bar());
    }

    /** @test */
    public function shouldAllowMockingProtectedMethodOnDefinitionTimePartial()
    {
        $mock = $this->container->mock("test\Mockery\TestWithProtectedMethods[protectedBar]")
            ->shouldAllowMockingProtectedMethods();

        $mock->shouldReceive("protectedBar")->andReturn("notbar");
        $this->assertEquals("notbar", $mock->bar());
    }

    /** @test */
    public function shouldAllowMockingAbstractProtectedMethods()
    {
        $mock = $this->container->mock("test\Mockery\TestWithProtectedMethods")
            ->shouldDeferMissing()
            ->shouldAllowMockingProtectedMethods();

        $mock->shouldReceive("abstractProtected")->andReturn("abstractProtected");
        $this->assertEquals("abstractProtected", $mock->foo());
    }
}


abstract class TestWithProtectedMethods
{
    public function foo()
    {
        return $this->abstractProtected();
    }

    abstract protected function abstractProtected();

    public function bar()
    {
        return $this->protectedBar();
    }

    protected function protectedBar()
    {
        return 'bar';
    }
}
MockingParameterAndReturnTypesTest.php000066400000010060151520664250014222 0ustar00<?php
/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mockery/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 *
 * @category   Mockery
 * @package    Mockery
 * @subpackage UnitTests
 * @copyright  Copyright (c) 2010-2014 Pádraic Brady (http://blog.astrumfutura.com)
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
 */

declare(strict_types=1); // Use strict types to ensure exact types are returned or passed

namespace test\Mockery;

use Mockery\Adapter\Phpunit\MockeryTestCase;

class MockingParameterAndReturnTypesTest extends MockeryTestCase
{
    public function setup()
    {
        $this->container = new \Mockery\Container;
    }

    public function teardown()
    {
        $this->container->mockery_close();
    }

    public function testMockingStringReturnType()
    {
        $mock = $this->container->mock("test\Mockery\TestWithParameterAndReturnType");

        $mock->shouldReceive("returnString");
        $this->assertSame("", $mock->returnString());
    }

    public function testMockingIntegerReturnType()
    {
        $mock = $this->container->mock("test\Mockery\TestWithParameterAndReturnType");

        $mock->shouldReceive("returnInteger");
        $this->assertEquals(0, $mock->returnInteger());
    }

    public function testMockingFloatReturnType()
    {
        $mock = $this->container->mock("test\Mockery\TestWithParameterAndReturnType");

        $mock->shouldReceive("returnFloat");
        $this->assertSame(0.0, $mock->returnFloat());
    }

    public function testMockingBooleanReturnType()
    {
        $mock = $this->container->mock("test\Mockery\TestWithParameterAndReturnType");

        $mock->shouldReceive("returnBoolean");
        $this->assertSame(false, $mock->returnBoolean());
    }

    public function testMockingArrayReturnType()
    {
        $mock = $this->container->mock("test\Mockery\TestWithParameterAndReturnType");

        $mock->shouldReceive("returnArray");
        $this->assertSame([], $mock->returnArray());
    }

    public function testMockingGeneratorReturnTyps()
    {
        $mock = $this->container->mock("test\Mockery\TestWithParameterAndReturnType");

        $mock->shouldReceive("returnGenerator");
        $this->assertInstanceOf("\Generator", $mock->returnGenerator());
    }

    public function testMockingCallableReturnType()
    {
        $mock = $this->container->mock("test\Mockery\TestWithParameterAndReturnType");

        $mock->shouldReceive("returnCallable");
        $this->assertTrue(is_callable($mock->returnCallable()));
    }

    public function testMockingClassReturnTypes()
    {
        $mock = $this->container->mock("test\Mockery\TestWithParameterAndReturnType");

        $mock->shouldReceive("withClassReturnType");
        $this->assertInstanceOf("test\Mockery\TestWithParameterAndReturnType", $mock->withClassReturnType());
    }

    public function testMockingParameterTypes()
    {
        $mock = $this->container->mock("test\Mockery\TestWithParameterAndReturnType");

        $mock->shouldReceive("withScalarParameters");
        $mock->withScalarParameters(1, 1.0, true, 'string');
    }
}


abstract class TestWithParameterAndReturnType
{
    public function returnString(): string
    {
    }

    public function returnInteger(): int
    {
    }

    public function returnFloat(): float
    {
    }

    public function returnBoolean(): bool
    {
    }

    public function returnArray(): array
    {
    }

    public function returnCallable(): callable
    {
    }

    public function returnGenerator(): \Generator
    {
    }

    public function withClassReturnType(): TestWithParameterAndReturnType
    {
    }

    public function withScalarParameters(int $integer, float $float, bool $boolean, string $string)
    {
    }
}
WithFormatterExpectationTest.php000066400000005762151520664250013142 0ustar00<?php
/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mockery/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 *
 * @category   Mockery
 * @package    Mockery
 * @subpackage UnitTests
 * @copyright  Copyright (c) 2010-2014 Pádraic Brady (http://blog.astrumfutura.com)
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
 */

class WithFormatterExpectationTest extends PHPUnit_Framework_TestCase
{
    /**
     * @dataProvider formatObjectsDataProvider
     */
    public function testFormatObjects($args, $expected)
    {
        $this->assertEquals(
            $expected,
            Mockery::formatObjects($args)
        );
    }

    /**
     * @expectedException Mockery\Exception\NoMatchingExpectationException
     *
     * Note that without the patch checked in with this test, rather than throwing
     * an exception, the program will go into an infinite recursive loop
     */
    public function testFormatObjectsWithMockCalledInGetterDoesNotLeadToRecursion()
    {
        $mock = Mockery::mock('stdClass');
        $mock->shouldReceive('doBar')->with('foo');
        $obj = new ClassWithGetter($mock);
        $obj->getFoo();
    }

    public function formatObjectsDataProvider()
    {
        return array(
            array(
                array(null),
                ''
            ),
            array(
                array('a string', 98768, array('a', 'nother', 'array')),
                ''
            ),
        );
    }

    /** @test */
    public function format_objects_should_not_call_getters_with_params()
    {
        $obj = new ClassWithGetterWithParam();
        $string = Mockery::formatObjects(array($obj));

        $this->assertNotContains('Missing argument 1 for', $string);
    }

    public function testFormatObjectsExcludesStaticProperties()
    {
        $obj = new ClassWithPublicStaticProperty();
        $string = Mockery::formatObjects(array($obj));

        $this->assertNotContains('excludedProperty', $string);
    }

    public function testFormatObjectsExcludesStaticGetters()
    {
        $obj = new ClassWithPublicStaticGetter();
        $string = Mockery::formatObjects(array($obj));

        $this->assertNotContains('getExcluded', $string);
    }
}

class ClassWithGetter
{
    private $dep;

    public function __construct($dep)
    {
        $this->dep = $dep;
    }

    public function getFoo()
    {
        return $this->dep->doBar('bar', $this);
    }
}

class ClassWithGetterWithParam
{
    public function getBar($bar)
    {
    }
}

class ClassWithPublicStaticProperty
{
    public static $excludedProperty;
}

class ClassWithPublicStaticGetter
{
    public static function getExcluded()
    {
    }
}
ExpectationTest.php000066400000210000151520664250010401 0ustar00<?php
/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mockery/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 *
 * @category   Mockery
 * @package    Mockery
 * @subpackage UnitTests
 * @copyright  Copyright (c) 2010-2014 Pádraic Brady (http://blog.astrumfutura.com)
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
 */

use Mockery\Adapter\Phpunit\MockeryTestCase;

class ExpectationTest extends MockeryTestCase
{

    public function setup()
    {
        $this->container = new \Mockery\Container(\Mockery::getDefaultGenerator(), \Mockery::getDefaultLoader());
        $this->mock = $this->container->mock('foo');
    }

    public function teardown()
    {
        \Mockery::getConfiguration()->allowMockingNonExistentMethods(true);
        $this->container->mockery_close();
    }

    public function testReturnsNullWhenNoArgs()
    {
        $this->mock->shouldReceive('foo');
        $this->assertNull($this->mock->foo());
    }

    public function testReturnsNullWhenSingleArg()
    {
        $this->mock->shouldReceive('foo');
        $this->assertNull($this->mock->foo(1));
    }

    public function testReturnsNullWhenManyArgs()
    {
        $this->mock->shouldReceive('foo');
        $this->assertNull($this->mock->foo('foo', array(), new stdClass));
    }

    public function testReturnsNullIfNullIsReturnValue()
    {
        $this->mock->shouldReceive('foo')->andReturn(null);
        $this->assertNull($this->mock->foo());
    }

    public function testReturnsNullForMockedExistingClassIfAndreturnnullCalled()
    {
        $mock = $this->container->mock('MockeryTest_Foo');
        $mock->shouldReceive('foo')->andReturn(null);
        $this->assertNull($mock->foo());
    }

    public function testReturnsNullForMockedExistingClassIfNullIsReturnValue()
    {
        $mock = $this->container->mock('MockeryTest_Foo');
        $mock->shouldReceive('foo')->andReturnNull();
        $this->assertNull($mock->foo());
    }

    public function testReturnsSameValueForAllIfNoArgsExpectationAndNoneGiven()
    {
        $this->mock->shouldReceive('foo')->andReturn(1);
        $this->assertEquals(1, $this->mock->foo());
    }

    public function testSetsPublicPropertyWhenRequested()
    {
        $this->mock->bar = null;
        $this->mock->shouldReceive('foo')->andSet('bar', 'baz');
        $this->assertNull($this->mock->bar);
        $this->mock->foo();
        $this->assertEquals('baz', $this->mock->bar);
    }

    public function testSetsPublicPropertyWhenRequestedUsingAlias()
    {
        $this->mock->bar = null;
        $this->mock->shouldReceive('foo')->set('bar', 'baz');
        $this->assertNull($this->mock->bar);
        $this->mock->foo();
        $this->assertEquals('baz', $this->mock->bar);
    }

    public function testSetsPublicPropertiesWhenRequested()
    {
        $this->mock->bar = null;
        $this->mock->shouldReceive('foo')->andSet('bar', 'baz', 'bazz', 'bazzz');
        $this->assertNull($this->mock->bar);
        $this->mock->foo();
        $this->assertEquals('baz', $this->mock->bar);
        $this->mock->foo();
        $this->assertEquals('bazz', $this->mock->bar);
        $this->mock->foo();
        $this->assertEquals('bazzz', $this->mock->bar);
    }

    public function testSetsPublicPropertiesWhenRequestedUsingAlias()
    {
        $this->mock->bar = null;
        $this->mock->shouldReceive('foo')->set('bar', 'baz', 'bazz', 'bazzz');
        $this->assertAttributeEmpty('bar', $this->mock);
        $this->mock->foo();
        $this->assertEquals('baz', $this->mock->bar);
        $this->mock->foo();
        $this->assertEquals('bazz', $this->mock->bar);
        $this->mock->foo();
        $this->assertEquals('bazzz', $this->mock->bar);
    }
    
    public function testSetsPublicPropertiesWhenRequestedMoreTimesThanSetValues()
    {
        $this->mock->bar = null;
        $this->mock->shouldReceive('foo')->andSet('bar', 'baz', 'bazz');
        $this->assertNull($this->mock->bar);
        $this->mock->foo();
        $this->assertEquals('baz', $this->mock->bar);
        $this->mock->foo();
        $this->assertEquals('bazz', $this->mock->bar);
        $this->mock->foo();
        $this->assertEquals('bazz', $this->mock->bar);
    }

    public function testSetsPublicPropertiesWhenRequestedMoreTimesThanSetValuesUsingAlias()
    {
        $this->mock->bar = null;
        $this->mock->shouldReceive('foo')->andSet('bar', 'baz', 'bazz');
        $this->assertNull($this->mock->bar);
        $this->mock->foo();
        $this->assertEquals('baz', $this->mock->bar);
        $this->mock->foo();
        $this->assertEquals('bazz', $this->mock->bar);
        $this->mock->foo();
        $this->assertEquals('bazz', $this->mock->bar);
    }

    public function testSetsPublicPropertiesWhenRequestedMoreTimesThanSetValuesWithDirectSet()
    {
        $this->mock->bar = null;
        $this->mock->shouldReceive('foo')->andSet('bar', 'baz', 'bazz');
        $this->assertNull($this->mock->bar);
        $this->mock->foo();
        $this->assertEquals('baz', $this->mock->bar);
        $this->mock->foo();
        $this->assertEquals('bazz', $this->mock->bar);
        $this->mock->bar = null;
        $this->mock->foo();
        $this->assertNull($this->mock->bar);
    }

    public function testSetsPublicPropertiesWhenRequestedMoreTimesThanSetValuesWithDirectSetUsingAlias()
    {
        $this->mock->bar = null;
        $this->mock->shouldReceive('foo')->set('bar', 'baz', 'bazz');
        $this->assertNull($this->mock->bar);
        $this->mock->foo();
        $this->assertEquals('baz', $this->mock->bar);
        $this->mock->foo();
        $this->assertEquals('bazz', $this->mock->bar);
        $this->mock->bar = null;
        $this->mock->foo();
        $this->assertNull($this->mock->bar);
    }

    public function testReturnsSameValueForAllIfNoArgsExpectationAndSomeGiven()
    {
        $this->mock->shouldReceive('foo')->andReturn(1);
        $this->assertEquals(1, $this->mock->foo('foo'));
    }

    public function testReturnsValueFromSequenceSequentially()
    {
        $this->mock->shouldReceive('foo')->andReturn(1, 2, 3);
        $this->mock->foo('foo');
        $this->assertEquals(2, $this->mock->foo('foo'));
    }

    public function testReturnsValueFromSequenceSequentiallyAndRepeatedlyReturnsFinalValueOnExtraCalls()
    {
        $this->mock->shouldReceive('foo')->andReturn(1, 2, 3);
        $this->mock->foo('foo');
        $this->mock->foo('foo');
        $this->assertEquals(3, $this->mock->foo('foo'));
        $this->assertEquals(3, $this->mock->foo('foo'));
    }

    public function testReturnsValueFromSequenceSequentiallyAndRepeatedlyReturnsFinalValueOnExtraCallsWithManyAndReturnCalls()
    {
        $this->mock->shouldReceive('foo')->andReturn(1)->andReturn(2, 3);
        $this->mock->foo('foo');
        $this->mock->foo('foo');
        $this->assertEquals(3, $this->mock->foo('foo'));
        $this->assertEquals(3, $this->mock->foo('foo'));
    }

    public function testReturnsValueOfClosure()
    {
        $this->mock->shouldReceive('foo')->with(5)->andReturnUsing(function ($v) {return $v+1;});
        $this->assertEquals(6, $this->mock->foo(5));
    }

    public function testReturnsUndefined()
    {
        $this->mock->shouldReceive('foo')->andReturnUndefined();
        $this->assertTrue($this->mock->foo() instanceof \Mockery\Undefined);
    }

    public function testReturnsValuesSetAsArray()
    {
        $this->mock->shouldReceive('foo')->andReturnValues(array(1, 2, 3));
        $this->assertEquals(1, $this->mock->foo());
        $this->assertEquals(2, $this->mock->foo());
        $this->assertEquals(3, $this->mock->foo());
    }

    /**
     * @expectedException OutOfBoundsException
     */
    public function testThrowsException()
    {
        $this->mock->shouldReceive('foo')->andThrow(new OutOfBoundsException);
        $this->mock->foo();
    }

    /**
     * @expectedException OutOfBoundsException
     */
    public function testThrowsExceptionBasedOnArgs()
    {
        $this->mock->shouldReceive('foo')->andThrow('OutOfBoundsException');
        $this->mock->foo();
    }

    public function testThrowsExceptionBasedOnArgsWithMessage()
    {
        $this->mock->shouldReceive('foo')->andThrow('OutOfBoundsException', 'foo');
        try {
            $this->mock->foo();
        } catch (OutOfBoundsException $e) {
            $this->assertEquals('foo', $e->getMessage());
        }
    }

    /**
     * @expectedException OutOfBoundsException
     */
    public function testThrowsExceptionSequentially()
    {
        $this->mock->shouldReceive('foo')->andThrow(new Exception)->andThrow(new OutOfBoundsException);
        try {
            $this->mock->foo();
        } catch (Exception $e) {
        }
        $this->mock->foo();
    }

    public function testAndThrowExceptions()
    {
        $this->mock->shouldReceive('foo')->andThrowExceptions(array(
            new OutOfBoundsException,
            new InvalidArgumentException,
        ));

        try {
            $this->mock->foo();
            throw new Exception("Expected OutOfBoundsException, non thrown");
        } catch (\Exception $e) {
            $this->assertInstanceOf("OutOfBoundsException", $e, "Wrong or no exception thrown: {$e->getMessage()}");
        }

        try {
            $this->mock->foo();
            throw new Exception("Expected InvalidArgumentException, non thrown");
        } catch (\Exception $e) {
            $this->assertInstanceOf("InvalidArgumentException", $e, "Wrong or no exception thrown: {$e->getMessage()}");
        }
    }

    /**
     * @expectedException Mockery\Exception
     * @expectedExceptionMessage You must pass an array of exception objects to andThrowExceptions
     */
    public function testAndThrowExceptionsCatchNonExceptionArgument()
    {
        $this->mock
            ->shouldReceive('foo')
            ->andThrowExceptions(array('NotAnException'));
    }

    public function testMultipleExpectationsWithReturns()
    {
        $this->mock->shouldReceive('foo')->with(1)->andReturn(10);
        $this->mock->shouldReceive('bar')->with(2)->andReturn(20);
        $this->assertEquals(10, $this->mock->foo(1));
        $this->assertEquals(20, $this->mock->bar(2));
    }

    public function testExpectsNoArguments()
    {
        $this->mock->shouldReceive('foo')->withNoArgs();
        $this->mock->foo();
    }

    /**
     * @expectedException \Mockery\Exception
     */
    public function testExpectsNoArgumentsThrowsExceptionIfAnyPassed()
    {
        $this->mock->shouldReceive('foo')->withNoArgs();
        $this->mock->foo(1);
    }

    public function testExpectsArgumentsArray()
    {
        $this->mock->shouldReceive('foo')->withArgs(array(1, 2));
        $this->mock->foo(1, 2);
    }

    /**
     * @expectedException \Mockery\Exception
     */
    public function testExpectsArgumentsArrayThrowsExceptionIfPassedEmptyArray()
    {
        $this->mock->shouldReceive('foo')->withArgs(array());
        $this->mock->foo(1, 2);
    }

    /**
     * @expectedException \Mockery\Exception
     */
    public function testExpectsArgumentsArrayThrowsExceptionIfNoArgumentsPassed()
    {
        $this->mock->shouldReceive('foo')->with();
        $this->mock->foo(1);
    }

    /**
     * @expectedException \Mockery\Exception
     */
    public function testExpectsArgumentsArrayThrowsExceptionIfPassedWrongArguments()
    {
        $this->mock->shouldReceive('foo')->withArgs(array(1, 2));
        $this->mock->foo(3, 4);
    }

    /**
     * @expectedException \Mockery\Exception
     * @expectedExceptionMessageRegExp /foo\(NULL\)/
     */
    public function testExpectsStringArgumentExceptionMessageDifferentiatesBetweenNullAndEmptyString()
    {
        $this->mock->shouldReceive('foo')->withArgs(array('a string'));
        $this->mock->foo(null);
    }

    public function testExpectsAnyArguments()
    {
        $this->mock->shouldReceive('foo')->withAnyArgs();
        $this->mock->foo();
        $this->mock->foo(1);
        $this->mock->foo(1, 'k', new stdClass);
    }

    public function testExpectsArgumentMatchingRegularExpression()
    {
        $this->mock->shouldReceive('foo')->with('/bar/i');
        $this->mock->foo('xxBARxx');
    }

    public function testExpectsArgumentMatchingObjectType()
    {
        $this->mock->shouldReceive('foo')->with('\stdClass');
        $this->mock->foo(new stdClass);
    }

    /**
     * @expectedException \Mockery\Exception
     */
    public function testThrowsExceptionOnNoArgumentMatch()
    {
        $this->mock->shouldReceive('foo')->with(1);
        $this->mock->foo(2);
    }

    public function testNeverCalled()
    {
        $this->mock->shouldReceive('foo')->never();
        $this->container->mockery_verify();
    }

    public function testShouldNotReceive()
    {
        $this->mock->shouldNotReceive('foo');
        $this->container->mockery_verify();
    }

    /**
     * @expectedException \Mockery\Exception\InvalidCountException
     */
    public function testShouldNotReceiveThrowsExceptionIfMethodCalled()
    {
        $this->mock->shouldNotReceive('foo');
        $this->mock->foo();
        $this->container->mockery_verify();
    }

    /**
     * @expectedException \Mockery\Exception\InvalidCountException
     */
    public function testShouldNotReceiveWithArgumentThrowsExceptionIfMethodCalled()
    {
        $this->mock->shouldNotReceive('foo')->with(2);
        $this->mock->foo(2);
        $this->container->mockery_verify();
    }

    /**
     * @expectedException \Mockery\CountValidator\Exception
     */
    public function testNeverCalledThrowsExceptionOnCall()
    {
        $this->mock->shouldReceive('foo')->never();
        $this->mock->foo();
        $this->container->mockery_verify();
    }

    public function testCalledOnce()
    {
        $this->mock->shouldReceive('foo')->once();
        $this->mock->foo();
        $this->container->mockery_verify();
    }

    /**
     * @expectedException \Mockery\CountValidator\Exception
     */
    public function testCalledOnceThrowsExceptionIfNotCalled()
    {
        $this->mock->shouldReceive('foo')->once();
        $this->container->mockery_verify();
    }

    /**
     * @expectedException \Mockery\CountValidator\Exception
     */
    public function testCalledOnceThrowsExceptionIfCalledTwice()
    {
        $this->mock->shouldReceive('foo')->once();
        $this->mock->foo();
        $this->mock->foo();
        $this->container->mockery_verify();
    }

    public function testCalledTwice()
    {
        $this->mock->shouldReceive('foo')->twice();
        $this->mock->foo();
        $this->mock->foo();
        $this->container->mockery_verify();
    }

    /**
     * @expectedException \Mockery\CountValidator\Exception
     */
    public function testCalledTwiceThrowsExceptionIfNotCalled()
    {
        $this->mock->shouldReceive('foo')->twice();
        $this->container->mockery_verify();
    }

    /**
     * @expectedException \Mockery\CountValidator\Exception
     */
    public function testCalledOnceThrowsExceptionIfCalledThreeTimes()
    {
        $this->mock->shouldReceive('foo')->twice();
        $this->mock->foo();
        $this->mock->foo();
        $this->mock->foo();
        $this->container->mockery_verify();
    }

    public function testCalledZeroOrMoreTimesAtZeroCalls()
    {
        $this->mock->shouldReceive('foo')->zeroOrMoreTimes();
        $this->container->mockery_verify();
    }

    public function testCalledZeroOrMoreTimesAtThreeCalls()
    {
        $this->mock->shouldReceive('foo')->zeroOrMoreTimes();
        $this->mock->foo();
        $this->mock->foo();
        $this->mock->foo();
        $this->container->mockery_verify();
    }

    public function testTimesCountCalls()
    {
        $this->mock->shouldReceive('foo')->times(4);
        $this->mock->foo();
        $this->mock->foo();
        $this->mock->foo();
        $this->mock->foo();
        $this->container->mockery_verify();
    }

    /**
     * @expectedException \Mockery\CountValidator\Exception
     */
    public function testTimesCountCallThrowsExceptionOnTooFewCalls()
    {
        $this->mock->shouldReceive('foo')->times(2);
        $this->mock->foo();
        $this->container->mockery_verify();
    }

    /**
     * @expectedException \Mockery\CountValidator\Exception
     */
    public function testTimesCountCallThrowsExceptionOnTooManyCalls()
    {
        $this->mock->shouldReceive('foo')->times(2);
        $this->mock->foo();
        $this->mock->foo();
        $this->mock->foo();
        $this->container->mockery_verify();
    }

    public function testCalledAtLeastOnceAtExactlyOneCall()
    {
        $this->mock->shouldReceive('foo')->atLeast()->once();
        $this->mock->foo();
        $this->container->mockery_verify();
    }

    public function testCalledAtLeastOnceAtExactlyThreeCalls()
    {
        $this->mock->shouldReceive('foo')->atLeast()->times(3);
        $this->mock->foo();
        $this->mock->foo();
        $this->mock->foo();
        $this->container->mockery_verify();
    }

    /**
     * @expectedException \Mockery\CountValidator\Exception
     */
    public function testCalledAtLeastThrowsExceptionOnTooFewCalls()
    {
        $this->mock->shouldReceive('foo')->atLeast()->twice();
        $this->mock->foo();
        $this->container->mockery_verify();
    }

    public function testCalledAtMostOnceAtExactlyOneCall()
    {
        $this->mock->shouldReceive('foo')->atMost()->once();
        $this->mock->foo();
        $this->container->mockery_verify();
    }

    public function testCalledAtMostAtExactlyThreeCalls()
    {
        $this->mock->shouldReceive('foo')->atMost()->times(3);
        $this->mock->foo();
        $this->mock->foo();
        $this->mock->foo();
        $this->container->mockery_verify();
    }

    /**
     * @expectedException \Mockery\CountValidator\Exception
     */
    public function testCalledAtLeastThrowsExceptionOnTooManyCalls()
    {
        $this->mock->shouldReceive('foo')->atMost()->twice();
        $this->mock->foo();
        $this->mock->foo();
        $this->mock->foo();
        $this->container->mockery_verify();
    }

    /**
     * @expectedException \Mockery\CountValidator\Exception
     */
    public function testExactCountersOverrideAnyPriorSetNonExactCounters()
    {
        $this->mock->shouldReceive('foo')->atLeast()->once()->once();
        $this->mock->foo();
        $this->mock->foo();
        $this->container->mockery_verify();
    }

    public function testComboOfLeastAndMostCallsWithOneCall()
    {
        $this->mock->shouldReceive('foo')->atleast()->once()->atMost()->twice();
        $this->mock->foo();
        $this->container->mockery_verify();
    }

    public function testComboOfLeastAndMostCallsWithTwoCalls()
    {
        $this->mock->shouldReceive('foo')->atleast()->once()->atMost()->twice();
        $this->mock->foo();
        $this->mock->foo();
        $this->container->mockery_verify();
    }

    /**
     * @expectedException \Mockery\CountValidator\Exception
     */
    public function testComboOfLeastAndMostCallsThrowsExceptionAtTooFewCalls()
    {
        $this->mock->shouldReceive('foo')->atleast()->once()->atMost()->twice();
        $this->container->mockery_verify();
    }

    /**
     * @expectedException \Mockery\CountValidator\Exception
     */
    public function testComboOfLeastAndMostCallsThrowsExceptionAtTooManyCalls()
    {
        $this->mock->shouldReceive('foo')->atleast()->once()->atMost()->twice();
        $this->mock->foo();
        $this->mock->foo();
        $this->mock->foo();
        $this->container->mockery_verify();
    }

    public function testCallCountingOnlyAppliesToMatchedExpectations()
    {
        $this->mock->shouldReceive('foo')->with(1)->once();
        $this->mock->shouldReceive('foo')->with(2)->twice();
        $this->mock->shouldReceive('foo')->with(3);
        $this->mock->foo(1);
        $this->mock->foo(2);
        $this->mock->foo(2);
        $this->mock->foo(3);
        $this->container->mockery_verify();
    }

    /**
     * @expectedException \Mockery\CountValidator\Exception
     */
    public function testCallCountingThrowsExceptionOnAnyMismatch()
    {
        $this->mock->shouldReceive('foo')->with(1)->once();
        $this->mock->shouldReceive('foo')->with(2)->twice();
        $this->mock->shouldReceive('foo')->with(3);
        $this->mock->shouldReceive('bar');
        $this->mock->foo(1);
        $this->mock->foo(2);
        $this->mock->foo(3);
        $this->mock->bar();
        $this->container->mockery_verify();
    }

    public function testOrderedCallsWithoutError()
    {
        $this->mock->shouldReceive('foo')->ordered();
        $this->mock->shouldReceive('bar')->ordered();
        $this->mock->foo();
        $this->mock->bar();
        $this->container->mockery_verify();
    }

    /**
     * @expectedException \Mockery\Exception
     */
    public function testOrderedCallsWithOutOfOrderError()
    {
        $this->mock->shouldReceive('foo')->ordered();
        $this->mock->shouldReceive('bar')->ordered();
        $this->mock->bar();
        $this->mock->foo();
        $this->container->mockery_verify();
    }

    public function testDifferentArgumentsAndOrderingsPassWithoutException()
    {
        $this->mock->shouldReceive('foo')->with(1)->ordered();
        $this->mock->shouldReceive('foo')->with(2)->ordered();
        $this->mock->foo(1);
        $this->mock->foo(2);
        $this->container->mockery_verify();
    }

    /**
     * @expectedException \Mockery\Exception
     */
    public function testDifferentArgumentsAndOrderingsThrowExceptionWhenInWrongOrder()
    {
        $this->mock->shouldReceive('foo')->with(1)->ordered();
        $this->mock->shouldReceive('foo')->with(2)->ordered();
        $this->mock->foo(2);
        $this->mock->foo(1);
        $this->container->mockery_verify();
    }

    public function testUnorderedCallsIgnoredForOrdering()
    {
        $this->mock->shouldReceive('foo')->with(1)->ordered();
        $this->mock->shouldReceive('foo')->with(2);
        $this->mock->shouldReceive('foo')->with(3)->ordered();
        $this->mock->foo(2);
        $this->mock->foo(1);
        $this->mock->foo(2);
        $this->mock->foo(3);
        $this->mock->foo(2);
        $this->container->mockery_verify();
    }

    public function testOrderingOfDefaultGrouping()
    {
        $this->mock->shouldReceive('foo')->ordered();
        $this->mock->shouldReceive('bar')->ordered();
        $this->mock->foo();
        $this->mock->bar();
        $this->container->mockery_verify();
    }

    /**
     * @expectedException \Mockery\Exception
     */
    public function testOrderingOfDefaultGroupingThrowsExceptionOnWrongOrder()
    {
        $this->mock->shouldReceive('foo')->ordered();
        $this->mock->shouldReceive('bar')->ordered();
        $this->mock->bar();
        $this->mock->foo();
        $this->container->mockery_verify();
    }

    public function testOrderingUsingNumberedGroups()
    {
        $this->mock->shouldReceive('start')->ordered(1);
        $this->mock->shouldReceive('foo')->ordered(2);
        $this->mock->shouldReceive('bar')->ordered(2);
        $this->mock->shouldReceive('final')->ordered();
        $this->mock->start();
        $this->mock->bar();
        $this->mock->foo();
        $this->mock->bar();
        $this->mock->final();
        $this->container->mockery_verify();
    }

    public function testOrderingUsingNamedGroups()
    {
        $this->mock->shouldReceive('start')->ordered('start');
        $this->mock->shouldReceive('foo')->ordered('foobar');
        $this->mock->shouldReceive('bar')->ordered('foobar');
        $this->mock->shouldReceive('final')->ordered();
        $this->mock->start();
        $this->mock->bar();
        $this->mock->foo();
        $this->mock->bar();
        $this->mock->final();
        $this->container->mockery_verify();
    }

    /**
     * @group 2A
     */
    public function testGroupedUngroupedOrderingDoNotOverlap()
    {
        $s = $this->mock->shouldReceive('start')->ordered();
        $m = $this->mock->shouldReceive('mid')->ordered('foobar');
        $e = $this->mock->shouldReceive('end')->ordered();
        $this->assertTrue($s->getOrderNumber() < $m->getOrderNumber());
        $this->assertTrue($m->getOrderNumber() < $e->getOrderNumber());
    }

    /**
     * @expectedException \Mockery\Exception
     */
    public function testGroupedOrderingThrowsExceptionWhenCallsDisordered()
    {
        $this->mock->shouldReceive('foo')->ordered('first');
        $this->mock->shouldReceive('bar')->ordered('second');
        $this->mock->bar();
        $this->mock->foo();
        $this->container->mockery_verify();
    }

    public function testExpectationMatchingWithNoArgsOrderings()
    {
        $this->mock->shouldReceive('foo')->withNoArgs()->once()->ordered();
        $this->mock->shouldReceive('bar')->withNoArgs()->once()->ordered();
        $this->mock->shouldReceive('foo')->withNoArgs()->once()->ordered();
        $this->mock->foo();
        $this->mock->bar();
        $this->mock->foo();
        $this->container->mockery_verify();
    }

    public function testExpectationMatchingWithAnyArgsOrderings()
    {
        $this->mock->shouldReceive('foo')->withAnyArgs()->once()->ordered();
        $this->mock->shouldReceive('bar')->withAnyArgs()->once()->ordered();
        $this->mock->shouldReceive('foo')->withAnyArgs()->once()->ordered();
        $this->mock->foo();
        $this->mock->bar();
        $this->mock->foo();
        $this->container->mockery_verify();
    }

    public function testEnsuresOrderingIsNotCrossMockByDefault()
    {
        $this->mock->shouldReceive('foo')->ordered();
        $mock2 = $this->container->mock('bar');
        $mock2->shouldReceive('bar')->ordered();
        $mock2->bar();
        $this->mock->foo();
    }

    /**
     * @expectedException \Mockery\Exception
     */
    public function testEnsuresOrderingIsCrossMockWhenGloballyFlagSet()
    {
        $this->mock->shouldReceive('foo')->globally()->ordered();
        $mock2 = $this->container->mock('bar');
        $mock2->shouldReceive('bar')->globally()->ordered();
        $mock2->bar();
        $this->mock->foo();
    }

    public function testExpectationCastToStringFormatting()
    {
        $exp = $this->mock->shouldReceive('foo')->with(1, 'bar', new stdClass, array('Spam' => 'Ham', 'Bar' => 'Baz'));
        $this->assertEquals('[foo(1, "bar", object(stdClass), array(\'Spam\'=>\'Ham\',\'Bar\'=>\'Baz\',))]', (string) $exp);
    }

    public function testLongExpectationCastToStringFormatting()
    {
        $exp = $this->mock->shouldReceive('foo')->with(array('Spam' => 'Ham', 'Bar' => 'Baz', 'Bar', 'Baz', 'Bar', 'Baz', 'Bar', 'Baz', 'Bar', 'Baz', 'Bar', 'Baz', 'Bar', 'Baz', 'Bar', 'Baz', 'Bar', 'Baz', 'Bar', 'Baz', 'Bar', 'Baz', 'Bar', 'Baz', 'Bar', 'Baz', 'Bar', 'Baz', 'Bar', 'Baz', 'Bar', 'Baz', 'Bar', 'Baz', 'Bar', 'Baz', 'Bar', 'Baz', 'Bar', 'Baz', 'Bar', 'Baz', 'Bar', 'Baz', 'Bar', 'Baz', 'Bar', 'Baz', 'Baz', 'Bar', 'Baz', 'Bar', 'Baz', 'Bar', 'Baz', 'Bar', 'Baz', 'Bar', 'Baz', 'Baz', 'Bar', 'Baz', 'Bar', 'Baz', 'Bar', 'Baz', 'Bar', 'Baz', 'Bar', 'Baz', 'Baz', 'Bar', 'Baz', 'Bar', 'Baz', 'Bar', 'Baz', 'Bar', 'Baz', 'Bar', 'Baz', 'Baz', 'Bar', 'Baz', 'Bar', 'Baz', 'Bar', 'Baz', 'Bar', 'Baz', 'Bar', 'Baz', 'Baz', 'Bar', 'Baz', 'Bar', 'Baz', 'Bar', 'Baz', 'Bar', 'Baz', 'Bar', 'Baz', 'Baz', 'Bar', 'Baz', 'Bar', 'Baz', 'Bar', 'Baz', 'Bar', 'Baz', 'Bar', 'Baz', 'Baz', 'Bar', 'Baz', 'Bar', 'Baz', 'Bar', 'Baz', 'Bar', 'Baz', 'Bar', 'Baz', 'Baz', 'Bar', 'Baz', 'Bar', 'Baz', 'Bar', 'Baz', 'Bar', 'Baz', 'Bar', 'Baz', 'Baz', 'Bar', 'Baz', 'Bar', 'Baz', 'Bar', 'Baz', 'Bar', 'Baz', 'Bar', 'Baz', 'End'));
        $this->assertEquals("[foo(array('Spam'=>'Ham','Bar'=>'Baz',0=>'Bar',1=>'Baz',2=>'Bar',3=>'Baz',4=>'Bar',5=>'Baz',6=>'Bar',7=>'Baz',8=>'Bar',9=>'Baz',10=>'Bar',11=>'Baz',12=>'Bar',13=>'Baz',14=>'Bar',15=>'Baz',16=>'Bar',17=>'Baz',18=>'Bar',19=>'Baz',20=>'Bar',21=>'Baz',22=>'Bar',23=>'Baz',24=>'Bar',25=>'Baz',26=>'Bar',27=>'Baz',28=>'Bar',29=>'Baz',30=>'Bar',31=>'Baz',32=>'Bar',33=>'Baz',34=>'Bar',35=>'Baz',36=>'Bar',37=>'Baz',38=>'Bar',39=>'Baz',40=>'Bar',41=>'Baz',42=>'Bar',43=>'Baz',44=>'Bar',45=>'Baz',46=>'Baz',47=>'Bar',48=>'Baz',49=>'Bar',50=>'Baz',51=>'Bar',52=>'Baz',53=>'Bar',54=>'Baz',55=>'Bar',56=>'Baz',57=>'Baz',58=>'Bar',59=>'Baz',60=>'Bar',61=>'Baz',62=>'Bar',63=>'Baz',64=>'Bar',65=>'Baz',66=>'Bar',67=>'Baz',68=>'Baz',69=>'Bar',70=>'Baz',71=>'Bar',72=>'Baz',73=>'Bar',74=>'Baz',75=>'Bar',76=>'Baz',77=>'Bar',78=>'Baz',79=>'Baz',80=>'Bar',81=>'Baz',82=>'Bar',83=>'Baz',84=>'Bar',85=>'Baz',86=>'Bar',87=>'Baz',88=>'Bar',89=>'Baz',90=>'Baz',91=>'Bar',92=>'Baz',93=>'Bar',94=>'Baz',95=>'Bar',96=>'Baz',97=>'Ba...))]", (string) $exp);
    }

    public function testMultipleExpectationCastToStringFormatting()
    {
        $exp = $this->mock->shouldReceive('foo', 'bar')->with(1);
        $this->assertEquals('[foo(1), bar(1)]', (string) $exp);
    }

    public function testGroupedOrderingWithLimitsAllowsMultipleReturnValues()
    {
        $this->mock->shouldReceive('foo')->with(2)->once()->andReturn('first');
        $this->mock->shouldReceive('foo')->with(2)->twice()->andReturn('second/third');
        $this->mock->shouldReceive('foo')->with(2)->andReturn('infinity');
        $this->assertEquals('first', $this->mock->foo(2));
        $this->assertEquals('second/third', $this->mock->foo(2));
        $this->assertEquals('second/third', $this->mock->foo(2));
        $this->assertEquals('infinity', $this->mock->foo(2));
        $this->assertEquals('infinity', $this->mock->foo(2));
        $this->assertEquals('infinity', $this->mock->foo(2));
        $this->container->mockery_verify();
    }

    public function testExpectationsCanBeMarkedAsDefaults()
    {
        $this->mock->shouldReceive('foo')->andReturn('bar')->byDefault();
        $this->assertEquals('bar', $this->mock->foo());
        $this->container->mockery_verify();
    }

    public function testDefaultExpectationsValidatedInCorrectOrder()
    {
        $this->mock->shouldReceive('foo')->with(1)->once()->andReturn('first')->byDefault();
        $this->mock->shouldReceive('foo')->with(2)->once()->andReturn('second')->byDefault();
        $this->assertEquals('first', $this->mock->foo(1));
        $this->assertEquals('second', $this->mock->foo(2));
        $this->container->mockery_verify();
    }

    public function testDefaultExpectationsAreReplacedByLaterConcreteExpectations()
    {
        $this->mock->shouldReceive('foo')->andReturn('bar')->once()->byDefault();
        $this->mock->shouldReceive('foo')->andReturn('bar')->twice();
        $this->mock->foo();
        $this->mock->foo();
        $this->container->mockery_verify();
    }

    public function testDefaultExpectationsCanBeChangedByLaterExpectations()
    {
        $this->mock->shouldReceive('foo')->with(1)->andReturn('bar')->once()->byDefault();
        $this->mock->shouldReceive('foo')->with(2)->andReturn('baz')->once();
        try {
            $this->mock->foo(1);
            $this->fail('Expected exception not thrown');
        } catch (\Mockery\Exception $e) {
        }
        $this->mock->foo(2);
        $this->container->mockery_verify();
    }

    /**
     * @expectedException \Mockery\Exception
     */
    public function testDefaultExpectationsCanBeOrdered()
    {
        $this->mock->shouldReceive('foo')->ordered()->byDefault();
        $this->mock->shouldReceive('bar')->ordered()->byDefault();
        $this->mock->bar();
        $this->mock->foo();
        $this->container->mockery_verify();
    }

    public function testDefaultExpectationsCanBeOrderedAndReplaced()
    {
        $this->mock->shouldReceive('foo')->ordered()->byDefault();
        $this->mock->shouldReceive('bar')->ordered()->byDefault();
        $this->mock->shouldReceive('bar')->ordered();
        $this->mock->shouldReceive('foo')->ordered();
        $this->mock->bar();
        $this->mock->foo();
        $this->container->mockery_verify();
    }

    public function testByDefaultOperatesFromMockConstruction()
    {
        $container = new \Mockery\Container(\Mockery::getDefaultGenerator(), \Mockery::getDefaultLoader());
        $mock = $container->mock('f', array('foo'=>'rfoo', 'bar'=>'rbar', 'baz'=>'rbaz'))->byDefault();
        $mock->shouldReceive('foo')->andReturn('foobar');
        $this->assertEquals('foobar', $mock->foo());
        $this->assertEquals('rbar', $mock->bar());
        $this->assertEquals('rbaz', $mock->baz());
        $mock->mockery_verify();
    }

    public function testByDefaultOnAMockDoesSquatWithoutExpectations()
    {
        $container = new \Mockery\Container(\Mockery::getDefaultGenerator(), \Mockery::getDefaultLoader());
        $mock = $container->mock('f')->byDefault();
    }

    public function testDefaultExpectationsCanBeOverridden()
    {
        $this->mock->shouldReceive('foo')->with('test')->andReturn('bar')->byDefault();
        $this->mock->shouldReceive('foo')->with('test')->andReturn('newbar')->byDefault();
        $this->mock->foo('test');
        $this->assertEquals('newbar', $this->mock->foo('test'));
    }

    /**
     * @expectedException \Mockery\Exception
     */
    public function testByDefaultPreventedFromSettingDefaultWhenDefaultingExpectationWasReplaced()
    {
        $exp = $this->mock->shouldReceive('foo')->andReturn(1);
        $this->mock->shouldReceive('foo')->andReturn(2);
        $exp->byDefault();
    }

    /**
     * Argument Constraint Tests
     */

    public function testAnyConstraintMatchesAnyArg()
    {
        $this->mock->shouldReceive('foo')->with(1, Mockery::any())->twice();
        $this->mock->foo(1, 2);
        $this->mock->foo(1, 'str');
        $this->container->mockery_verify();
    }

    public function testAnyConstraintNonMatchingCase()
    {
        $this->mock->shouldReceive('foo')->times(3);
        $this->mock->shouldReceive('foo')->with(1, Mockery::any())->never();
        $this->mock->foo();
        $this->mock->foo(1);
        $this->mock->foo(1, 2, 3);
        $this->container->mockery_verify();
    }

    public function testArrayConstraintMatchesArgument()
    {
        $this->mock->shouldReceive('foo')->with(Mockery::type('array'))->once();
        $this->mock->foo(array());
        $this->container->mockery_verify();
    }

    public function testArrayConstraintNonMatchingCase()
    {
        $this->mock->shouldReceive('foo')->times(3);
        $this->mock->shouldReceive('foo')->with(1, Mockery::type('array'))->never();
        $this->mock->foo();
        $this->mock->foo(1);
        $this->mock->foo(1, 2, 3);
        $this->container->mockery_verify();
    }

    /**
     * @expectedException \Mockery\Exception
     */
    public function testArrayConstraintThrowsExceptionWhenConstraintUnmatched()
    {
        $this->mock->shouldReceive('foo')->with(Mockery::type('array'))->once();
        $this->mock->foo(1);
        $this->container->mockery_verify();
    }

    public function testBoolConstraintMatchesArgument()
    {
        $this->mock->shouldReceive('foo')->with(Mockery::type('bool'))->once();
        $this->mock->foo(true);
        $this->container->mockery_verify();
    }

    public function testBoolConstraintNonMatchingCase()
    {
        $this->mock->shouldReceive('foo')->times(3);
        $this->mock->shouldReceive('foo')->with(1, Mockery::type('bool'))->never();
        $this->mock->foo();
        $this->mock->foo(1);
        $this->mock->foo(1, 2, 3);
        $this->container->mockery_verify();
    }

    /**
     * @expectedException \Mockery\Exception
     */
    public function testBoolConstraintThrowsExceptionWhenConstraintUnmatched()
    {
        $this->mock->shouldReceive('foo')->with(Mockery::type('bool'))->once();
        $this->mock->foo(1);
        $this->container->mockery_verify();
    }

    public function testCallableConstraintMatchesArgument()
    {
        $this->mock->shouldReceive('foo')->with(Mockery::type('callable'))->once();
        $this->mock->foo(function () {return 'f';});
        $this->container->mockery_verify();
    }

    public function testCallableConstraintNonMatchingCase()
    {
        $this->mock->shouldReceive('foo')->times(3);
        $this->mock->shouldReceive('foo')->with(1, Mockery::type('callable'))->never();
        $this->mock->foo();
        $this->mock->foo(1);
        $this->mock->foo(1, 2, 3);
        $this->container->mockery_verify();
    }

    /**
     * @expectedException \Mockery\Exception
     */
    public function testCallableConstraintThrowsExceptionWhenConstraintUnmatched()
    {
        $this->mock->shouldReceive('foo')->with(Mockery::type('callable'))->once();
        $this->mock->foo(1);
        $this->container->mockery_verify();
    }

    public function testDoubleConstraintMatchesArgument()
    {
        $this->mock->shouldReceive('foo')->with(Mockery::type('double'))->once();
        $this->mock->foo(2.25);
        $this->container->mockery_verify();
    }

    public function testDoubleConstraintNonMatchingCase()
    {
        $this->mock->shouldReceive('foo')->times(3);
        $this->mock->shouldReceive('foo')->with(1, Mockery::type('double'))->never();
        $this->mock->foo();
        $this->mock->foo(1);
        $this->mock->foo(1, 2, 3);
        $this->container->mockery_verify();
    }

    /**
     * @expectedException \Mockery\Exception
     */
    public function testDoubleConstraintThrowsExceptionWhenConstraintUnmatched()
    {
        $this->mock->shouldReceive('foo')->with(Mockery::type('double'))->once();
        $this->mock->foo(1);
        $this->container->mockery_verify();
    }

    public function testFloatConstraintMatchesArgument()
    {
        $this->mock->shouldReceive('foo')->with(Mockery::type('float'))->once();
        $this->mock->foo(2.25);
        $this->container->mockery_verify();
    }

    public function testFloatConstraintNonMatchingCase()
    {
        $this->mock->shouldReceive('foo')->times(3);
        $this->mock->shouldReceive('foo')->with(1, Mockery::type('float'))->never();
        $this->mock->foo();
        $this->mock->foo(1);
        $this->mock->foo(1, 2, 3);
        $this->container->mockery_verify();
    }

    /**
     * @expectedException \Mockery\Exception
     */
    public function testFloatConstraintThrowsExceptionWhenConstraintUnmatched()
    {
        $this->mock->shouldReceive('foo')->with(Mockery::type('float'))->once();
        $this->mock->foo(1);
        $this->container->mockery_verify();
    }

    public function testIntConstraintMatchesArgument()
    {
        $this->mock->shouldReceive('foo')->with(Mockery::type('int'))->once();
        $this->mock->foo(2);
        $this->container->mockery_verify();
    }

    public function testIntConstraintNonMatchingCase()
    {
        $this->mock->shouldReceive('foo')->times(3);
        $this->mock->shouldReceive('foo')->with(1, Mockery::type('int'))->never();
        $this->mock->foo();
        $this->mock->foo(1);
        $this->mock->foo(1, 2, 3);
        $this->container->mockery_verify();
    }

    /**
     * @expectedException \Mockery\Exception
     */
    public function testIntConstraintThrowsExceptionWhenConstraintUnmatched()
    {
        $this->mock->shouldReceive('foo')->with(Mockery::type('int'))->once();
        $this->mock->foo('f');
        $this->container->mockery_verify();
    }

    public function testLongConstraintMatchesArgument()
    {
        $this->mock->shouldReceive('foo')->with(Mockery::type('long'))->once();
        $this->mock->foo(2);
        $this->container->mockery_verify();
    }

    public function testLongConstraintNonMatchingCase()
    {
        $this->mock->shouldReceive('foo')->times(3);
        $this->mock->shouldReceive('foo')->with(1, Mockery::type('long'))->never();
        $this->mock->foo();
        $this->mock->foo(1);
        $this->mock->foo(1, 2, 3);
        $this->container->mockery_verify();
    }

    /**
     * @expectedException \Mockery\Exception
     */
    public function testLongConstraintThrowsExceptionWhenConstraintUnmatched()
    {
        $this->mock->shouldReceive('foo')->with(Mockery::type('long'))->once();
        $this->mock->foo('f');
        $this->container->mockery_verify();
    }

    public function testNullConstraintMatchesArgument()
    {
        $this->mock->shouldReceive('foo')->with(Mockery::type('null'))->once();
        $this->mock->foo(null);
        $this->container->mockery_verify();
    }

    public function testNullConstraintNonMatchingCase()
    {
        $this->mock->shouldReceive('foo')->times(3);
        $this->mock->shouldReceive('foo')->with(1, Mockery::type('null'))->never();
        $this->mock->foo();
        $this->mock->foo(1);
        $this->mock->foo(1, 2, 3);
        $this->container->mockery_verify();
    }

    /**
     * @expectedException \Mockery\Exception
     */
    public function testNullConstraintThrowsExceptionWhenConstraintUnmatched()
    {
        $this->mock->shouldReceive('foo')->with(Mockery::type('null'))->once();
        $this->mock->foo('f');
        $this->container->mockery_verify();
    }

    public function testNumericConstraintMatchesArgument()
    {
        $this->mock->shouldReceive('foo')->with(Mockery::type('numeric'))->once();
        $this->mock->foo('2');
        $this->container->mockery_verify();
    }

    public function testNumericConstraintNonMatchingCase()
    {
        $this->mock->shouldReceive('foo')->times(3);
        $this->mock->shouldReceive('foo')->with(1, Mockery::type('numeric'))->never();
        $this->mock->foo();
        $this->mock->foo(1);
        $this->mock->foo(1, 2, 3);
        $this->container->mockery_verify();
    }

    /**
     * @expectedException \Mockery\Exception
     */
    public function testNumericConstraintThrowsExceptionWhenConstraintUnmatched()
    {
        $this->mock->shouldReceive('foo')->with(Mockery::type('numeric'))->once();
        $this->mock->foo('f');
        $this->container->mockery_verify();
    }

    public function testObjectConstraintMatchesArgument()
    {
        $this->mock->shouldReceive('foo')->with(Mockery::type('stdClass'))->once();
        $this->mock->foo(new stdClass);
        $this->container->mockery_verify();
    }

    public function testObjectConstraintNonMatchingCase()
    {
        $this->mock->shouldReceive('foo')->times(3);
        $this->mock->shouldReceive('foo')->with(1, Mockery::type('stdClass`'))->never();
        $this->mock->foo();
        $this->mock->foo(1);
        $this->mock->foo(1, 2, 3);
        $this->container->mockery_verify();
    }

    /**
     * @expectedException \Mockery\Exception
     */
    public function testObjectConstraintThrowsExceptionWhenConstraintUnmatched()
    {
        $this->mock->shouldReceive('foo')->with(Mockery::type('stdClass'))->once();
        $this->mock->foo('f');
        $this->container->mockery_verify();
    }

    public function testRealConstraintMatchesArgument()
    {
        $this->mock->shouldReceive('foo')->with(Mockery::type('real'))->once();
        $this->mock->foo(2.25);
        $this->container->mockery_verify();
    }

    public function testRealConstraintNonMatchingCase()
    {
        $this->mock->shouldReceive('foo')->times(3);
        $this->mock->shouldReceive('foo')->with(1, Mockery::type('real'))->never();
        $this->mock->foo();
        $this->mock->foo(1);
        $this->mock->foo(1, 2, 3);
        $this->container->mockery_verify();
    }

    /**
     * @expectedException \Mockery\Exception
     */
    public function testRealConstraintThrowsExceptionWhenConstraintUnmatched()
    {
        $this->mock->shouldReceive('foo')->with(Mockery::type('real'))->once();
        $this->mock->foo('f');
        $this->container->mockery_verify();
    }

    public function testResourceConstraintMatchesArgument()
    {
        $this->mock->shouldReceive('foo')->with(Mockery::type('resource'))->once();
        $r = fopen(dirname(__FILE__) . '/_files/file.txt', 'r');
        $this->mock->foo($r);
        $this->container->mockery_verify();
    }

    public function testResourceConstraintNonMatchingCase()
    {
        $this->mock->shouldReceive('foo')->times(3);
        $this->mock->shouldReceive('foo')->with(1, Mockery::type('resource'))->never();
        $this->mock->foo();
        $this->mock->foo(1);
        $this->mock->foo(1, 2, 3);
        $this->container->mockery_verify();
    }

    /**
     * @expectedException \Mockery\Exception
     */
    public function testResourceConstraintThrowsExceptionWhenConstraintUnmatched()
    {
        $this->mock->shouldReceive('foo')->with(Mockery::type('resource'))->once();
        $this->mock->foo('f');
        $this->container->mockery_verify();
    }

    public function testScalarConstraintMatchesArgument()
    {
        $this->mock->shouldReceive('foo')->with(Mockery::type('scalar'))->once();
        $this->mock->foo(2);
        $this->container->mockery_verify();
    }

    public function testScalarConstraintNonMatchingCase()
    {
        $this->mock->shouldReceive('foo')->times(3);
        $this->mock->shouldReceive('foo')->with(1, Mockery::type('scalar'))->never();
        $this->mock->foo();
        $this->mock->foo(1);
        $this->mock->foo(1, 2, 3);
        $this->container->mockery_verify();
    }

    /**
     * @expectedException \Mockery\Exception
     */
    public function testScalarConstraintThrowsExceptionWhenConstraintUnmatched()
    {
        $this->mock->shouldReceive('foo')->with(Mockery::type('scalar'))->once();
        $this->mock->foo(array());
        $this->container->mockery_verify();
    }

    public function testStringConstraintMatchesArgument()
    {
        $this->mock->shouldReceive('foo')->with(Mockery::type('string'))->once();
        $this->mock->foo('2');
        $this->container->mockery_verify();
    }

    public function testStringConstraintNonMatchingCase()
    {
        $this->mock->shouldReceive('foo')->times(3);
        $this->mock->shouldReceive('foo')->with(1, Mockery::type('string'))->never();
        $this->mock->foo();
        $this->mock->foo(1);
        $this->mock->foo(1, 2, 3);
        $this->container->mockery_verify();
    }

    /**
     * @expectedException \Mockery\Exception
     */
    public function testStringConstraintThrowsExceptionWhenConstraintUnmatched()
    {
        $this->mock->shouldReceive('foo')->with(Mockery::type('string'))->once();
        $this->mock->foo(1);
        $this->container->mockery_verify();
    }

    public function testClassConstraintMatchesArgument()
    {
        $this->mock->shouldReceive('foo')->with(Mockery::type('stdClass'))->once();
        $this->mock->foo(new stdClass);
        $this->container->mockery_verify();
    }

    public function testClassConstraintNonMatchingCase()
    {
        $this->mock->shouldReceive('foo')->times(3);
        $this->mock->shouldReceive('foo')->with(1, Mockery::type('stdClass'))->never();
        $this->mock->foo();
        $this->mock->foo(1);
        $this->mock->foo(1, 2, 3);
        $this->container->mockery_verify();
    }

    /**
     * @expectedException \Mockery\Exception
     */
    public function testClassConstraintThrowsExceptionWhenConstraintUnmatched()
    {
        $this->mock->shouldReceive('foo')->with(Mockery::type('stdClass'))->once();
        $this->mock->foo(new Exception);
        $this->container->mockery_verify();
    }

    public function testDucktypeConstraintMatchesArgument()
    {
        $this->mock->shouldReceive('foo')->with(Mockery::ducktype('quack', 'swim'))->once();
        $this->mock->foo(new Mockery_Duck);
        $this->container->mockery_verify();
    }

    public function testDucktypeConstraintNonMatchingCase()
    {
        $this->mock->shouldReceive('foo')->times(3);
        $this->mock->shouldReceive('foo')->with(1, Mockery::ducktype('quack', 'swim'))->never();
        $this->mock->foo();
        $this->mock->foo(1);
        $this->mock->foo(1, 2, 3);
        $this->container->mockery_verify();
    }

    /**
     * @expectedException \Mockery\Exception
     */
    public function testDucktypeConstraintThrowsExceptionWhenConstraintUnmatched()
    {
        $this->mock->shouldReceive('foo')->with(Mockery::ducktype('quack', 'swim'))->once();
        $this->mock->foo(new Mockery_Duck_Nonswimmer);
        $this->container->mockery_verify();
    }

    public function testArrayContentConstraintMatchesArgument()
    {
        $this->mock->shouldReceive('foo')->with(Mockery::subset(array('a'=>1, 'b'=>2)))->once();
        $this->mock->foo(array('a'=>1, 'b'=>2, 'c'=>3));
        $this->container->mockery_verify();
    }

    public function testArrayContentConstraintNonMatchingCase()
    {
        $this->mock->shouldReceive('foo')->times(3);
        $this->mock->shouldReceive('foo')->with(1, Mockery::subset(array('a'=>1, 'b'=>2)))->never();
        $this->mock->foo();
        $this->mock->foo(1);
        $this->mock->foo(1, 2, 3);
        $this->container->mockery_verify();
    }

    /**
     * @expectedException \Mockery\Exception
     */
    public function testArrayContentConstraintThrowsExceptionWhenConstraintUnmatched()
    {
        $this->mock->shouldReceive('foo')->with(Mockery::subset(array('a'=>1, 'b'=>2)))->once();
        $this->mock->foo(array('a'=>1, 'c'=>3));
        $this->container->mockery_verify();
    }

    public function testContainsConstraintMatchesArgument()
    {
        $this->mock->shouldReceive('foo')->with(Mockery::contains(1, 2))->once();
        $this->mock->foo(array('a'=>1, 'b'=>2, 'c'=>3));
        $this->container->mockery_verify();
    }

    public function testContainsConstraintNonMatchingCase()
    {
        $this->mock->shouldReceive('foo')->times(3);
        $this->mock->shouldReceive('foo')->with(1, Mockery::contains(1, 2))->never();
        $this->mock->foo();
        $this->mock->foo(1);
        $this->mock->foo(1, 2, 3);
        $this->container->mockery_verify();
    }

    /**
     * @expectedException \Mockery\Exception
     */
    public function testContainsConstraintThrowsExceptionWhenConstraintUnmatched()
    {
        $this->mock->shouldReceive('foo')->with(Mockery::contains(1, 2))->once();
        $this->mock->foo(array('a'=>1, 'c'=>3));
        $this->container->mockery_verify();
    }

    public function testHasKeyConstraintMatchesArgument()
    {
        $this->mock->shouldReceive('foo')->with(Mockery::hasKey('c'))->once();
        $this->mock->foo(array('a'=>1, 'b'=>2, 'c'=>3));
        $this->container->mockery_verify();
    }

    public function testHasKeyConstraintNonMatchingCase()
    {
        $this->mock->shouldReceive('foo')->times(3);
        $this->mock->shouldReceive('foo')->with(1, Mockery::hasKey('a'))->never();
        $this->mock->foo();
        $this->mock->foo(1);
        $this->mock->foo(1, array('a'=>1), 3);
        $this->container->mockery_verify();
    }

    /**
     * @expectedException \Mockery\Exception
     */
    public function testHasKeyConstraintThrowsExceptionWhenConstraintUnmatched()
    {
        $this->mock->shouldReceive('foo')->with(Mockery::hasKey('c'))->once();
        $this->mock->foo(array('a'=>1, 'b'=>3));
        $this->container->mockery_verify();
    }

    public function testHasValueConstraintMatchesArgument()
    {
        $this->mock->shouldReceive('foo')->with(Mockery::hasValue(1))->once();
        $this->mock->foo(array('a'=>1, 'b'=>2, 'c'=>3));
        $this->container->mockery_verify();
    }

    public function testHasValueConstraintNonMatchingCase()
    {
        $this->mock->shouldReceive('foo')->times(3);
        $this->mock->shouldReceive('foo')->with(1, Mockery::hasValue(1))->never();
        $this->mock->foo();
        $this->mock->foo(1);
        $this->mock->foo(1, array('a'=>1), 3);
        $this->container->mockery_verify();
    }

    /**
     * @expectedException \Mockery\Exception
     */
    public function testHasValueConstraintThrowsExceptionWhenConstraintUnmatched()
    {
        $this->mock->shouldReceive('foo')->with(Mockery::hasValue(2))->once();
        $this->mock->foo(array('a'=>1, 'b'=>3));
        $this->container->mockery_verify();
    }

    public function testOnConstraintMatchesArgument_ClosureEvaluatesToTrue()
    {
        $function = function ($arg) {return $arg % 2 == 0;};
        $this->mock->shouldReceive('foo')->with(Mockery::on($function))->once();
        $this->mock->foo(4);
        $this->container->mockery_verify();
    }

    /**
     * @expectedException \Mockery\Exception
     */
    public function testOnConstraintThrowsExceptionWhenConstraintUnmatched_ClosureEvaluatesToFalse()
    {
        $function = function ($arg) {return $arg % 2 == 0;};
        $this->mock->shouldReceive('foo')->with(Mockery::on($function))->once();
        $this->mock->foo(5);
        $this->container->mockery_verify();
    }

    public function testMustBeConstraintMatchesArgument()
    {
        $this->mock->shouldReceive('foo')->with(Mockery::mustBe(2))->once();
        $this->mock->foo(2);
        $this->container->mockery_verify();
    }

    public function testMustBeConstraintNonMatchingCase()
    {
        $this->mock->shouldReceive('foo')->times(3);
        $this->mock->shouldReceive('foo')->with(1, Mockery::mustBe(2))->never();
        $this->mock->foo();
        $this->mock->foo(1);
        $this->mock->foo(1, 2, 3);
        $this->container->mockery_verify();
    }

    /**
     * @expectedException \Mockery\Exception
     */
    public function testMustBeConstraintThrowsExceptionWhenConstraintUnmatched()
    {
        $this->mock->shouldReceive('foo')->with(Mockery::mustBe(2))->once();
        $this->mock->foo('2');
        $this->container->mockery_verify();
    }

    public function testMustBeConstraintMatchesObjectArgumentWithEqualsComparisonNotIdentical()
    {
        $a = new stdClass;
        $a->foo = 1;
        $b = new stdClass;
        $b->foo = 1;
        $this->mock->shouldReceive('foo')->with(Mockery::mustBe($a))->once();
        $this->mock->foo($b);
        $this->container->mockery_verify();
    }

    public function testMustBeConstraintNonMatchingCaseWithObject()
    {
        $a = new stdClass;
        $a->foo = 1;
        $this->mock->shouldReceive('foo')->times(3);
        $this->mock->shouldReceive('foo')->with(1, Mockery::mustBe($a))->never();
        $this->mock->foo();
        $this->mock->foo(1);
        $this->mock->foo(1, $a, 3);
        $this->container->mockery_verify();
    }

    /**
     * @expectedException \Mockery\Exception
     */
    public function testMustBeConstraintThrowsExceptionWhenConstraintUnmatchedWithObject()
    {
        $a = new stdClass;
        $a->foo = 1;
        $b = new stdClass;
        $b->foo = 2;
        $this->mock->shouldReceive('foo')->with(Mockery::mustBe($a))->once();
        $this->mock->foo($b);
        $this->container->mockery_verify();
    }

    public function testMatchPrecedenceBasedOnExpectedCallsFavouringExplicitMatch()
    {
        $this->mock->shouldReceive('foo')->with(1)->once();
        $this->mock->shouldReceive('foo')->with(Mockery::any())->never();
        $this->mock->foo(1);
        $this->container->mockery_verify();
    }

    public function testMatchPrecedenceBasedOnExpectedCallsFavouringAnyMatch()
    {
        $this->mock->shouldReceive('foo')->with(Mockery::any())->once();
        $this->mock->shouldReceive('foo')->with(1)->never();
        $this->mock->foo(1);
        $this->container->mockery_verify();
    }

    public function testReturnNullIfIgnoreMissingMethodsSet()
    {
        $this->mock->shouldIgnoreMissing();
        $this->assertNull($this->mock->g(1, 2));
    }

    public function testReturnUndefinedIfIgnoreMissingMethodsSet()
    {
        $this->mock->shouldIgnoreMissing()->asUndefined();
        $this->assertTrue($this->mock->g(1, 2) instanceof \Mockery\Undefined);
    }

    public function testReturnAsUndefinedAllowsForInfiniteSelfReturningChain()
    {
        $this->mock->shouldIgnoreMissing()->asUndefined();
        $this->assertTrue($this->mock->g(1, 2)->a()->b()->c() instanceof \Mockery\Undefined);
    }

    public function testShouldIgnoreMissingFluentInterface()
    {
        $this->assertTrue($this->mock->shouldIgnoreMissing() instanceof \Mockery\MockInterface);
    }

    public function testShouldIgnoreMissingAsUndefinedFluentInterface()
    {
        $this->assertTrue($this->mock->shouldIgnoreMissing()->asUndefined() instanceof \Mockery\MockInterface);
    }

    public function testShouldIgnoreMissingAsDefinedProxiesToUndefinedAllowingToString()
    {
        $this->mock->shouldIgnoreMissing()->asUndefined();
        $string = "Method call: {$this->mock->g()}";
        $string = "Mock: {$this->mock}";
    }

    public function testShouldIgnoreMissingDefaultReturnValue()
    {
        $this->mock->shouldIgnoreMissing(1);
        $this->assertEquals(1, $this->mock->a());
    }

    /** @issue #253 */
    public function testShouldIgnoreMissingDefaultSelfAndReturnsSelf()
    {
        $this->mock->shouldIgnoreMissing($this->container->self());
        $this->assertSame($this->mock, $this->mock->a()->b());
    }

    public function testToStringMagicMethodCanBeMocked()
    {
        $this->mock->shouldReceive("__toString")->andReturn('dave');
        $this->assertEquals("{$this->mock}", "dave");
    }

    public function testOptionalMockRetrieval()
    {
        $m = $this->container->mock('f')->shouldReceive('foo')->with(1)->andReturn(3)->mock();
        $this->assertTrue($m instanceof \Mockery\MockInterface);
    }

    public function testNotConstraintMatchesArgument()
    {
        $this->mock->shouldReceive('foo')->with(Mockery::not(1))->once();
        $this->mock->foo(2);
        $this->container->mockery_verify();
    }

    public function testNotConstraintNonMatchingCase()
    {
        $this->mock->shouldReceive('foo')->times(3);
        $this->mock->shouldReceive('foo')->with(1, Mockery::not(2))->never();
        $this->mock->foo();
        $this->mock->foo(1);
        $this->mock->foo(1, 2, 3);
        $this->container->mockery_verify();
    }

    /**
     * @expectedException \Mockery\Exception
     */
    public function testNotConstraintThrowsExceptionWhenConstraintUnmatched()
    {
        $this->mock->shouldReceive('foo')->with(Mockery::not(2))->once();
        $this->mock->foo(2);
        $this->container->mockery_verify();
    }

    public function testAnyOfConstraintMatchesArgument()
    {
        $this->mock->shouldReceive('foo')->with(Mockery::anyOf(1, 2))->twice();
        $this->mock->foo(2);
        $this->mock->foo(1);
        $this->container->mockery_verify();
    }

    public function testAnyOfConstraintNonMatchingCase()
    {
        $this->mock->shouldReceive('foo')->times(3);
        $this->mock->shouldReceive('foo')->with(1, Mockery::anyOf(1, 2))->never();
        $this->mock->foo();
        $this->mock->foo(1);
        $this->mock->foo(1, 2, 3);
        $this->container->mockery_verify();
    }

    /**
     * @expectedException \Mockery\Exception
     */
    public function testAnyOfConstraintThrowsExceptionWhenConstraintUnmatched()
    {
        $this->mock->shouldReceive('foo')->with(Mockery::anyOf(1, 2))->once();
        $this->mock->foo(3);
        $this->container->mockery_verify();
    }

    public function testNotAnyOfConstraintMatchesArgument()
    {
        $this->mock->shouldReceive('foo')->with(Mockery::notAnyOf(1, 2))->once();
        $this->mock->foo(3);
        $this->container->mockery_verify();
    }

    public function testNotAnyOfConstraintNonMatchingCase()
    {
        $this->mock->shouldReceive('foo')->times(3);
        $this->mock->shouldReceive('foo')->with(1, Mockery::notAnyOf(1, 2))->never();
        $this->mock->foo();
        $this->mock->foo(1);
        $this->mock->foo(1, 4, 3);
        $this->container->mockery_verify();
    }

    /**
     * @expectedException \Mockery\Exception
     */
    public function testNotAnyOfConstraintThrowsExceptionWhenConstraintUnmatched()
    {
        $this->mock->shouldReceive('foo')->with(Mockery::notAnyOf(1, 2))->once();
        $this->mock->foo(2);
        $this->container->mockery_verify();
    }

    /**
     * @expectedException \Mockery\Exception
     */
    public function testGlobalConfigMayForbidMockingNonExistentMethodsOnClasses()
    {
        \Mockery::getConfiguration()->allowMockingNonExistentMethods(false);
        $mock = $this->container->mock('stdClass');
        $mock->shouldReceive('foo');
    }

    /**
     * @expectedException \Mockery\Exception
     * @expectedExceptionMessage Mockery's configuration currently forbids mocking
     */
    public function testGlobalConfigMayForbidMockingNonExistentMethodsOnAutoDeclaredClasses()
    {
        \Mockery::getConfiguration()->allowMockingNonExistentMethods(false);
        $mock = $this->container->mock('SomeMadeUpClass');
        $mock->shouldReceive('foo');
    }

    /**
     * @expectedException \Mockery\Exception
     */
    public function testGlobalConfigMayForbidMockingNonExistentMethodsOnObjects()
    {
        \Mockery::getConfiguration()->allowMockingNonExistentMethods(false);
        $mock = $this->container->mock(new stdClass);
        $mock->shouldReceive('foo');
    }

    public function testAnExampleWithSomeExpectationAmends()
    {
        $service = $this->container->mock('MyService');
        $service->shouldReceive('login')->with('user', 'pass')->once()->andReturn(true);
        $service->shouldReceive('hasBookmarksTagged')->with('php')->once()->andReturn(false);
        $service->shouldReceive('addBookmark')->with('/^http:/', \Mockery::type('string'))->times(3)->andReturn(true);
        $service->shouldReceive('hasBookmarksTagged')->with('php')->once()->andReturn(true);

        $this->assertTrue($service->login('user', 'pass'));
        $this->assertFalse($service->hasBookmarksTagged('php'));
        $this->assertTrue($service->addBookmark('http://example.com/1', 'some_tag1'));
        $this->assertTrue($service->addBookmark('http://example.com/2', 'some_tag2'));
        $this->assertTrue($service->addBookmark('http://example.com/3', 'some_tag3'));
        $this->assertTrue($service->hasBookmarksTagged('php'));

        $this->container->mockery_verify();
    }

    public function testAnExampleWithSomeExpectationAmendsOnCallCounts()
    {
        $service = $this->container->mock('MyService');
        $service->shouldReceive('login')->with('user', 'pass')->once()->andReturn(true);
        $service->shouldReceive('hasBookmarksTagged')->with('php')->once()->andReturn(false);
        $service->shouldReceive('addBookmark')->with('/^http:/', \Mockery::type('string'))->times(3)->andReturn(true);
        $service->shouldReceive('hasBookmarksTagged')->with('php')->twice()->andReturn(true);

        $this->assertTrue($service->login('user', 'pass'));
        $this->assertFalse($service->hasBookmarksTagged('php'));
        $this->assertTrue($service->addBookmark('http://example.com/1', 'some_tag1'));
        $this->assertTrue($service->addBookmark('http://example.com/2', 'some_tag2'));
        $this->assertTrue($service->addBookmark('http://example.com/3', 'some_tag3'));
        $this->assertTrue($service->hasBookmarksTagged('php'));
        $this->assertTrue($service->hasBookmarksTagged('php'));

        $this->container->mockery_verify();
    }

    public function testAnExampleWithSomeExpectationAmendsOnCallCounts_PHPUnitTest()
    {
        $service = $this->getMock('MyService2');
        $service->expects($this->once())->method('login')->with('user', 'pass')->will($this->returnValue(true));
        $service->expects($this->exactly(3))->method('hasBookmarksTagged')->with('php')
            ->will($this->onConsecutiveCalls(false, true, true));
        $service->expects($this->exactly(3))->method('addBookmark')
            ->with($this->matchesRegularExpression('/^http:/'), $this->isType('string'))
            ->will($this->returnValue(true));

        $this->assertTrue($service->login('user', 'pass'));
        $this->assertFalse($service->hasBookmarksTagged('php'));
        $this->assertTrue($service->addBookmark('http://example.com/1', 'some_tag1'));
        $this->assertTrue($service->addBookmark('http://example.com/2', 'some_tag2'));
        $this->assertTrue($service->addBookmark('http://example.com/3', 'some_tag3'));
        $this->assertTrue($service->hasBookmarksTagged('php'));
        $this->assertTrue($service->hasBookmarksTagged('php'));
    }

    public function testMockedMethodsCallableFromWithinOriginalClass()
    {
        $mock = $this->container->mock('MockeryTest_InterMethod1[doThird]');
        $mock->shouldReceive('doThird')->andReturn(true);
        $this->assertTrue($mock->doFirst());
    }

    /**
     * @group issue #20
     */
    public function testMockingDemeterChainsPassesMockeryExpectationToCompositeExpectation()
    {
        $mock = $this->container->mock('Mockery_Demeterowski');
        $mock->shouldReceive('foo->bar->baz')->andReturn('Spam!');
        $demeter = new Mockery_UseDemeter($mock);
        $this->assertSame('Spam!', $demeter->doit());
    }

    /**
     * @group issue #20 - with args in demeter chain
     */
    public function testMockingDemeterChainsPassesMockeryExpectationToCompositeExpectationWithArgs()
    {
        $mock = $this->container->mock('Mockery_Demeterowski');
        $mock->shouldReceive('foo->bar->baz')->andReturn('Spam!');
        $demeter = new Mockery_UseDemeter($mock);
        $this->assertSame('Spam!', $demeter->doitWithArgs());
    }

    public function testPassthruEnsuresRealMethodCalledForReturnValues()
    {
        $mock = $this->container->mock('MockeryTest_SubjectCall1');
        $mock->shouldReceive('foo')->once()->passthru();
        $this->assertEquals('bar', $mock->foo());
        $this->container->mockery_verify();
    }

    public function testShouldIgnoreMissingExpectationBasedOnArgs()
    {
        $mock = $this->container->mock("MyService2")->shouldIgnoreMissing();
        $mock->shouldReceive("hasBookmarksTagged")->with("dave")->once();
        $mock->hasBookmarksTagged("dave");
        $mock->hasBookmarksTagged("padraic");
        $this->container->mockery_verify();
    }

    public function testShouldDeferMissingExpectationBasedOnArgs()
    {
        $mock = $this->container->mock("MockeryTest_SubjectCall1")->shouldDeferMissing();

        $this->assertEquals('bar', $mock->foo());
        $this->assertEquals('bar', $mock->foo("baz"));
        $this->assertEquals('bar', $mock->foo("qux"));

        $mock->shouldReceive("foo")->with("baz")->twice()->andReturn('123');
        $this->assertEquals('bar', $mock->foo());
        $this->assertEquals('123', $mock->foo("baz"));
        $this->assertEquals('bar', $mock->foo("qux"));

        $mock->shouldReceive("foo")->withNoArgs()->once()->andReturn('456');
        $this->assertEquals('456', $mock->foo());
        $this->assertEquals('123', $mock->foo("baz"));
        $this->assertEquals('bar', $mock->foo("qux"));

        $this->container->mockery_verify();
    }

    public function testCanReturnSelf()
    {
        $this->mock->shouldReceive("foo")->andReturnSelf();
        $this->assertSame($this->mock, $this->mock->foo());
    }

    public function testExpectationCanBeOverridden()
    {
        $this->mock->shouldReceive('foo')->once()->andReturn('green');
        $this->mock->shouldReceive('foo')->andReturn('blue');
        $this->assertEquals($this->mock->foo(), 'green');
        $this->assertEquals($this->mock->foo(), 'blue');
    }
}

class MockeryTest_SubjectCall1
{
    public function foo()
    {
        return 'bar';
    }
}

class MockeryTest_InterMethod1
{
    public function doFirst()
    {
        return $this->doSecond();
    }

    private function doSecond()
    {
        return $this->doThird();
    }

    public function doThird()
    {
        return false;
    }
}

class MyService2
{
    public function login($user, $pass)
    {
    }
    public function hasBookmarksTagged($tag)
    {
    }
    public function addBookmark($uri, $tag)
    {
    }
}

class Mockery_Duck
{
    public function quack()
    {
    }
    public function swim()
    {
    }
}

class Mockery_Duck_Nonswimmer
{
    public function quack()
    {
    }
}

class Mockery_Demeterowski
{
    public function foo()
    {
        return $this;
    }
    public function bar()
    {
        return $this;
    }
    public function baz()
    {
        return 'Ham!';
    }
}

class Mockery_UseDemeter
{
    public function __construct($demeter)
    {
        $this->demeter = $demeter;
    }
    public function doit()
    {
        return $this->demeter->foo()->bar()->baz();
    }
    public function doitWithArgs()
    {
        return $this->demeter->foo("foo")->bar("bar")->baz("baz");
    }
}

class MockeryTest_Foo
{
    public function foo()
    {
    }
}
MockeryCanMockMultipleInterfacesWhichOverlapTest.php000066400000003321151520664250017025 0ustar00<?php

namespace Mockery\Tests;

/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mockery/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 *
 * @category   Mockery
 * @package    Mockery
 * @subpackage UnitTests
 * @copyright  Copyright (c) 2010-2014 Pádraic Brady (http://blog.astrumfutura.com)
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
 */

use Mockery\Adapter\Phpunit\MockeryTestCase;

class GeneratorTest extends MockeryTestCase
{
    /** @test */
    public function shouldNotDuplicateDoublyInheritedMethods()
    {
        $container = new \Mockery\Container;
        $mock = $container->mock('Mockery\Tests\Evenement_EventEmitter', 'Mockery\Tests\Chatroulette_ConnectionInterface');
    }
}

interface Evenement_EventEmitterInterface
{
    public function on($name, $callback);
}

class Evenement_EventEmitter implements Evenement_EventEmitterInterface
{
    public function on($name, $callback)
    {
    }
}

interface React_StreamInterface extends Evenement_EventEmitterInterface
{
    public function close();
}

interface React_ReadableStreamInterface extends React_StreamInterface
{
    public function pause();
}

interface React_WritableStreamInterface extends React_StreamInterface
{
    public function write($data);
}

interface Chatroulette_ConnectionInterface extends React_ReadableStreamInterface, React_WritableStreamInterface
{
}
Generator/DefinedTargetClassTest.php000066400000001413151520664250013545 0ustar00<?php

namespace Mockery;

use Mockery\Generator\DefinedTargetClass;

class DefinedTargetClassTest extends \PHPUnit_Framework_TestCase
{
    /** @test */
    public function it_knows_if_one_of_its_ancestors_is_internal()
    {
        $target = new DefinedTargetClass(new \ReflectionClass("ArrayObject"));
        $this->assertTrue($target->hasInternalAncestor());

        $target = new DefinedTargetClass(new \ReflectionClass("Mockery\MockeryTest_ClassThatExtendsArrayObject"));
        $this->assertTrue($target->hasInternalAncestor());

        $target = new DefinedTargetClass(new \ReflectionClass("Mockery\DefinedTargetClassTest"));
        $this->assertFalse($target->hasInternalAncestor());
    }
}

class MockeryTest_ClassThatExtendsArrayObject extends \ArrayObject
{
}
Generator/MockConfigurationTest.php000066400000012262151520664250013477 0ustar00<?php

namespace Mockery\Generator;

class MockConfigurationTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @test
     */
    public function blackListedMethodsShouldNotBeInListToBeMocked()
    {
        $config = new MockConfiguration(array("Mockery\Generator\\TestSubject"), array("foo"));

        $methods = $config->getMethodsToMock();
        $this->assertEquals(1, count($methods));
        $this->assertEquals("bar", $methods[0]->getName());
    }

    /**
     * @test
     */
    public function blackListsAreCaseInsensitive()
    {
        $config = new MockConfiguration(array("Mockery\Generator\\TestSubject"), array("FOO"));

        $methods = $config->getMethodsToMock();
        $this->assertEquals(1, count($methods));
        $this->assertEquals("bar", $methods[0]->getName());
    }


    /**
     * @test
     */
    public function onlyWhiteListedMethodsShouldBeInListToBeMocked()
    {
        $config = new MockConfiguration(array("Mockery\Generator\\TestSubject"), array(), array('foo'));

        $methods = $config->getMethodsToMock();
        $this->assertEquals(1, count($methods));
        $this->assertEquals("foo", $methods[0]->getName());
    }

    /**
     * @test
     */
    public function whitelistOverRulesBlackList()
    {
        $config = new MockConfiguration(array("Mockery\Generator\\TestSubject"), array("foo"), array("foo"));

        $methods = $config->getMethodsToMock();
        $this->assertEquals(1, count($methods));
        $this->assertEquals("foo", $methods[0]->getName());
    }

    /**
     * @test
     */
    public function whiteListsAreCaseInsensitive()
    {
        $config = new MockConfiguration(array("Mockery\Generator\\TestSubject"), array(), array("FOO"));

        $methods = $config->getMethodsToMock();
        $this->assertEquals(1, count($methods));
        $this->assertEquals("foo", $methods[0]->getName());
    }

    /**
     * @test
     */
    public function finalMethodsAreExcluded()
    {
        $config = new MockConfiguration(array("Mockery\Generator\\ClassWithFinalMethod"));

        $methods = $config->getMethodsToMock();
        $this->assertEquals(1, count($methods));
        $this->assertEquals("bar", $methods[0]->getName());
    }

    /**
     * @test
     */
    public function shouldIncludeMethodsFromAllTargets()
    {
        $config = new MockConfiguration(array("Mockery\\Generator\\TestInterface", "Mockery\\Generator\\TestInterface2"));
        $methods = $config->getMethodsToMock();
        $this->assertEquals(2, count($methods));
    }

    /**
     * @test
     * @expectedException Mockery\Exception
     */
    public function shouldThrowIfTargetClassIsFinal()
    {
        $config = new MockConfiguration(array("Mockery\\Generator\\TestFinal"));
        $config->getTargetClass();
    }

    /**
     * @test
     */
    public function shouldTargetIteratorAggregateIfTryingToMockTraversable()
    {
        $config = new MockConfiguration(array("\\Traversable"));

        $interfaces = $config->getTargetInterfaces();
        $this->assertEquals(1, count($interfaces));
        $first = array_shift($interfaces);
        $this->assertEquals("IteratorAggregate", $first->getName());
    }

    /**
     * @test
     */
    public function shouldTargetIteratorAggregateIfTraversableInTargetsTree()
    {
        $config = new MockConfiguration(array("Mockery\Generator\TestTraversableInterface"));

        $interfaces = $config->getTargetInterfaces();
        $this->assertEquals(2, count($interfaces));
        $this->assertEquals("IteratorAggregate", $interfaces[0]->getName());
        $this->assertEquals("Mockery\Generator\TestTraversableInterface", $interfaces[1]->getName());
    }

    /**
     * @test
     */
    public function shouldBringIteratorToHeadOfTargetListIfTraversablePresent()
    {
        $config = new MockConfiguration(array("Mockery\Generator\TestTraversableInterface2"));

        $interfaces = $config->getTargetInterfaces();
        $this->assertEquals(2, count($interfaces));
        $this->assertEquals("Iterator", $interfaces[0]->getName());
        $this->assertEquals("Mockery\Generator\TestTraversableInterface2", $interfaces[1]->getName());
    }

    /**
     * @test
     */
    public function shouldBringIteratorAggregateToHeadOfTargetListIfTraversablePresent()
    {
        $config = new MockConfiguration(array("Mockery\Generator\TestTraversableInterface3"));

        $interfaces = $config->getTargetInterfaces();
        $this->assertEquals(2, count($interfaces));
        $this->assertEquals("IteratorAggregate", $interfaces[0]->getName());
        $this->assertEquals("Mockery\Generator\TestTraversableInterface3", $interfaces[1]->getName());
    }
}

interface TestTraversableInterface extends \Traversable
{
}
interface TestTraversableInterface2 extends \Traversable, \Iterator
{
}
interface TestTraversableInterface3 extends \Traversable, \IteratorAggregate
{
}

final class TestFinal
{
}

interface TestInterface
{
    public function foo();
}

interface TestInterface2
{
    public function bar();
}

class TestSubject
{
    public function foo()
    {
    }

    public function bar()
    {
    }
}

class ClassWithFinalMethod
{
    final public function foo()
    {
    }

    public function bar()
    {
    }
}
Generator/StringManipulation/Pass/CallTypeHintPassTest.php000066400000002272151520664250020002 0ustar00<?php

namespace Mockery\Test\Generator\StringManipulation\Pass;

use Mockery as m;
use Mockery\Generator\StringManipulation\Pass\CallTypeHintPass;

class CallTypeHintPassTest extends \PHPUnit_Framework_TestCase
{
    const CODE = ' public function __call($method, array $args) {}
                   public static function __callStatic($method, array $args) {}
    ';

    /**
     * @test
     */
    public function shouldRemoveCallTypeHintIfRequired()
    {
        $pass = new CallTypeHintPass;
        $config = m::mock("Mockery\Generator\MockConfiguration", array(
            "requiresCallTypeHintRemoval" => true,
        ))->shouldDeferMissing();
        $code = $pass->apply(static::CODE, $config);
        $this->assertContains('__call($method, $args)', $code);
    }

    /**
     * @test
     */
    public function shouldRemoveCallStaticTypeHintIfRequired()
    {
        $pass = new CallTypeHintPass;
        $config = m::mock("Mockery\Generator\MockConfiguration", array(
            "requiresCallStaticTypeHintRemoval" => true,
        ))->shouldDeferMissing();
        $code = $pass->apply(static::CODE, $config);
        $this->assertContains('__callStatic($method, $args)', $code);
    }
}
Generator/StringManipulation/Pass/ClassNamePassTest.php000066400000003161151520664250017306 0ustar00<?php

namespace Mockery\Generator\StringManipulation\Pass;

use Mockery as m;
use Mockery\Generator\MockConfiguration;
use Mockery\Generator\StringManipulation\Pass\ClassNamePass;

class ClassNamePassTest extends \PHPUnit_Framework_TestCase
{
    const CODE = "namespace Mockery; class Mock {}";

    public function setup()
    {
        $this->pass = new ClassNamePass();
    }

    /**
     * @test
     */
    public function shouldRemoveNamespaceDefinition()
    {
        $config = new MockConfiguration(array(), array(), array(), "Dave\Dave");
        $code = $this->pass->apply(static::CODE, $config);
        $this->assertNotContains('namespace Mockery;', $code);
    }

    /**
     * @test
     */
    public function shouldReplaceNamespaceIfClassNameIsNamespaced()
    {
        $config = new MockConfiguration(array(), array(), array(), "Dave\Dave");
        $code = $this->pass->apply(static::CODE, $config);
        $this->assertNotContains('namespace Mockery;', $code);
        $this->assertContains('namespace Dave;', $code);
    }

    /**
     * @test
     */
    public function shouldReplaceClassNameWithSpecifiedName()
    {
        $config = new MockConfiguration(array(), array(), array(), "Dave");
        $code = $this->pass->apply(static::CODE, $config);
        $this->assertContains('class Dave', $code);
    }

    /**
     * @test
     */
    public function shouldRemoveLeadingBackslashesFromNamespace()
    {
        $config = new MockConfiguration(array(), array(), array(), "\Dave\Dave");
        $code = $this->pass->apply(static::CODE, $config);
        $this->assertContains('namespace Dave;', $code);
    }
}
Generator/StringManipulation/Pass/InstanceMockPassTest.php000066400000001373151520664250020021 0ustar00<?php

namespace Mockery\Test\Generator\StringManipulation\Pass;

use Mockery as m;
use Mockery\Generator\MockConfigurationBuilder;
use Mockery\Generator\StringManipulation\Pass\InstanceMockPass;

class InstanceMockPassTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @test
     */
    public function shouldAppendConstructorAndPropertyForInstanceMock()
    {
        $builder = new MockConfigurationBuilder;
        $builder->setInstanceMock(true);
        $config = $builder->getMockConfiguration();
        $pass = new InstanceMockPass;
        $code = $pass->apply('class Dave { }', $config);
        $this->assertContains('public function __construct', $code);
        $this->assertContains('protected $_mockery_ignoreVerification', $code);
    }
}
Generator/StringManipulation/Pass/InterfacePassTest.php000066400000002325151520664250017341 0ustar00<?php

namespace Mockery\Test\Generator\StringManipulation\Pass;

use Mockery as m;
use Mockery\Generator\MockConfiguration;
use Mockery\Generator\StringManipulation\Pass\InterfacePass;

class InterfacePassTest extends \PHPUnit_Framework_TestCase
{
    const CODE = "class Mock implements MockInterface";

    /**
     * @test
     */
    public function shouldNotAlterCodeIfNoTargetInterfaces()
    {
        $pass = new InterfacePass;

        $config = m::mock("Mockery\Generator\MockConfiguration", array(
            "getTargetInterfaces" => array(),
        ));

        $code = $pass->apply(static::CODE, $config);
        $this->assertEquals(static::CODE, $code);
    }

    /**
     * @test
     */
    public function shouldAddAnyInterfaceNamesToImplementsDefinition()
    {
        $pass = new InterfacePass;

        $config = m::mock("Mockery\Generator\MockConfiguration", array(
            "getTargetInterfaces" => array(
                m::mock(array("getName" => "Dave\Dave")),
                m::mock(array("getName" => "Paddy\Paddy")),
            ),
        ));

        $code = $pass->apply(static::CODE, $config);

        $this->assertContains("implements MockInterface, \Dave\Dave, \Paddy\Paddy", $code);
    }
}
GlobalHelpersTest.php000066400000003064151520664250010653 0ustar00<?php
/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mockery/blob/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 *
 * @category   Mockery
 * @package    Mockery
 * @copyright  Copyright (c) 2016 Dave Marshall
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
 */

use PHPUnit\Framework\TestCase;

class GlobalHelpersTest extends TestCase
{
    public function setup()
    {
        \Mockery::globalHelpers();
    }

    public function tearDown()
    {
        \Mockery::close();
    }

    /** @test */
    public function mock_creates_a_mock()
    {
        $double = mock();

        $this->assertInstanceOf('Mockery\MockInterface', $double);
        $this->setExpectedException('Exception');
        $double->foo();
    }

    /** @test */
    public function spy_creates_a_spy()
    {
        $double = spy();

        $this->assertInstanceOf('Mockery\MockInterface', $double);
        $double->foo();
    }

    /** @test */
    public function named_mock_creates_a_named_mock()
    {
        $className = "Class".uniqid();
        $double = namedMock($className);

        $this->assertInstanceOf('Mockery\MockInterface', $double);
        $this->assertInstanceOf($className, $double);
    }
}
HamcrestExpectationTest.php000066400000003727151520664250012110 0ustar00<?php
/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mockery/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 *
 * @category   Mockery
 * @package    Mockery
 * @subpackage UnitTests
 * @copyright  Copyright (c) 2010-2014 Pádraic Brady (http://blog.astrumfutura.com)
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
 */

use Mockery\Adapter\Phpunit\MockeryTestCase;

class HamcrestExpectationTest extends MockeryTestCase
{

    public function setUp()
    {
        $this->container = new \Mockery\Container(\Mockery::getDefaultGenerator(), \Mockery::getDefaultLoader());
        $this->mock = $this->container->mock('foo');
    }


    public function tearDown()
    {
        \Mockery::getConfiguration()->allowMockingNonExistentMethods(true);
        $this->container->mockery_close();
    }

    /** Just a quickie roundup of a few Hamcrest matchers to check nothing obvious out of place **/

    public function testAnythingConstraintMatchesArgument()
    {
        $this->mock->shouldReceive('foo')->with(anything())->once();
        $this->mock->foo(2);
        $this->container->mockery_verify();
    }

    public function testGreaterThanConstraintMatchesArgument()
    {
        $this->mock->shouldReceive('foo')->with(greaterThan(1))->once();
        $this->mock->foo(2);
        $this->container->mockery_verify();
    }

    /**
     * @expectedException Mockery\Exception
     */
    public function testGreaterThanConstraintNotMatchesArgument()
    {
        $this->mock->shouldReceive('foo')->with(greaterThan(1))->once();
        $this->mock->foo(1);
        $this->container->mockery_verify();
    }
}
MockingMethodsWithNullableParametersTest.php000066400000011616151520664250015404 0ustar00<?php
/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mockery/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 *
 * @category   Mockery
 * @package    Mockery
 * @subpackage UnitTests
 * @copyright  Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
 */

namespace test\Mockery;

use Mockery\Adapter\Phpunit\MockeryTestCase;
use test\Mockery\Fixtures\MethodWithNullableReturnType;

/**
 * @requires PHP 7.1.0RC3
 */
class MockingMethodsWithNullableParametersTest extends MockeryTestCase
{
    /**
     * @var \Mockery\Container
     */
    private $container;

    protected function setUp()
    {
        require_once __DIR__."/Fixtures/MethodWithNullableParameters.php";

        $this->container = new \Mockery\Container;
    }

    protected function tearDown()
    {
        $this->container->mockery_close();
    }

    /**
     * @test
     */
    public function itShouldAllowNonNullableTypeToBeSet()
    {
        $mock = $this->container->mock('test\Mockery\Fixtures\MethodWithNullableParameters');

        $mock->shouldReceive('nonNullablePrimitive')->with('a string');
        $mock->nonNullablePrimitive('a string');
    }

    /**
     * @test
     * @expectedException \TypeError
     */
    public function itShouldNotAllowNonNullToBeNull()
    {
        $mock = $this->container->mock('test\Mockery\Fixtures\MethodWithNullableParameters');

        $mock->nonNullablePrimitive(null);
    }

    /**
     * @test
     */
    public function itShouldAllowPrimitiveNullableToBeNull()
    {
        $mock = $this->container->mock('test\Mockery\Fixtures\MethodWithNullableParameters');

        $mock->shouldReceive('nullablePrimitive')->with(null);
        $mock->nullablePrimitive(null);
    }

    /**
     * @test
     */
    public function itShouldAllowPrimitiveNullabeToBeSet()
    {
        $mock = $this->container->mock('test\Mockery\Fixtures\MethodWithNullableParameters');

        $mock->shouldReceive('nullablePrimitive')->with('a string');
        $mock->nullablePrimitive('a string');
    }
    /**
     * @test
     */
    public function itShouldAllowSelfToBeSet()
    {
        $obj = new \test\Mockery\Fixtures\MethodWithNullableParameters;
        $mock = $this->container->mock('test\Mockery\Fixtures\MethodWithNullableParameters');

        $mock->shouldReceive('nonNullableSelf')->with($obj);
        $mock->nonNullableSelf($obj);
    }

    /**
     * @test
     * @expectedException \TypeError
     */
    public function itShouldNotAllowSelfToBeNull()
    {
        $mock = $this->container->mock('test\Mockery\Fixtures\MethodWithNullableParameters');

        $mock->nonNullableSelf(null);
    }

    /**
     * @test
     */
    public function itShouldAllowNullalbeSelfToBeSet()
    {
        $obj = new \test\Mockery\Fixtures\MethodWithNullableParameters;

        $mock = $this->container->mock('test\Mockery\Fixtures\MethodWithNullableParameters');

        $mock->shouldReceive('nullableSelf')->with($obj);
        $mock->nullableSelf($obj);
    }

    /**
     * @test
     */
    public function itShouldAllowNullableSelfToBeNull()
    {
        $mock = $this->container->mock('test\Mockery\Fixtures\MethodWithNullableParameters');

        $mock->shouldReceive('nullableClass')->with(null);
        $mock->nullableClass(null);
    }

    /**
     * @test
     */
    public function itShouldAllowClassToBeSet()
    {
        $obj = new \test\Mockery\Fixtures\MethodWithNullableParameters;
        $mock = $this->container->mock('test\Mockery\Fixtures\MethodWithNullableParameters');

        $mock->shouldReceive('nonNullableClass')->with($obj);
        $mock->nonNullableClass($obj);
    }

    /**
     * @test
     * @expectedException \TypeError
     */
    public function itShouldNotAllowClassToBeNull()
    {
        $mock = $this->container->mock('test\Mockery\Fixtures\MethodWithNullableParameters');

        $mock->nonNullableClass(null);
    }

    /**
     * @test
     */
    public function itShouldAllowNullalbeClassToBeSet()
    {
        $obj = new \test\Mockery\Fixtures\MethodWithNullableParameters;

        $mock = $this->container->mock('test\Mockery\Fixtures\MethodWithNullableParameters');

        $mock->shouldReceive('nullableClass')->with($obj);
        $mock->nullableClass($obj);
    }

    /**
     * @test
     */
    public function itShouldAllowNullableClassToBeNull()
    {
        $mock = $this->container->mock('test\Mockery\Fixtures\MethodWithNullableParameters');

        $mock->shouldReceive('nullableClass')->with(null);
        $mock->nullableClass(null);
    }
}
SpyTest.php000066400000004144151520664250006703 0ustar00<?php

namespace test\Mockery;

use Mockery as m;
use Mockery\Spy;

class SpyTest extends \PHPUnit_Framework_TestCase
{
    public function setup()
    {
        $this->container = new \Mockery\Container;
    }

    public function teardown()
    {
        $this->container->mockery_close();
    }

    /** @test */
    public function itVerifiesAMethodWasCalled()
    {
        $spy = m::spy();
        $spy->myMethod();
        $spy->shouldHaveReceived("myMethod");

        $this->setExpectedException("Mockery\Exception\InvalidCountException");
        $spy->shouldHaveReceived("someMethodThatWasNotCalled");
    }

    /** @test */
    public function itVerifiesAMethodWasNotCalled()
    {
        $spy = m::spy();
        $spy->shouldNotHaveReceived("myMethod");

        $this->setExpectedException("Mockery\Exception\InvalidCountException");
        $spy->myMethod();
        $spy->shouldNotHaveReceived("myMethod");
    }

    /** @test */
    public function itVerifiesAMethodWasNotCalledWithParticularArguments()
    {
        $spy = m::spy();
        $spy->myMethod(123, 456);

        $spy->shouldNotHaveReceived("myMethod", array(789, 10));

        $this->setExpectedException("Mockery\Exception\InvalidCountException");
        $spy->shouldNotHaveReceived("myMethod", array(123, 456));
    }

    /** @test */
    public function itVerifiesAMethodWasCalledASpecificNumberOfTimes()
    {
        $spy = m::spy();
        $spy->myMethod();
        $spy->myMethod();
        $spy->shouldHaveReceived("myMethod")->twice();

        $this->setExpectedException("Mockery\Exception\InvalidCountException");
        $spy->myMethod();
        $spy->shouldHaveReceived("myMethod")->twice();
    }

    /** @test */
    public function itVerifiesAMethodWasCalledWithSpecificArguments()
    {
        $spy = m::spy();
        $spy->myMethod(123, "a string");
        $spy->shouldHaveReceived("myMethod")->with(123, "a string");
        $spy->shouldHaveReceived("myMethod", array(123, "a string"));

        $this->setExpectedException("Mockery\Exception\InvalidCountException");
        $spy->shouldHaveReceived("myMethod")->with(123);
    }
}
DemeterChainTest.php000066400000011414151520664250010456 0ustar00<?php
/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mockery/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 *
 * @category   Mockery
 * @package    Mockery
 * @subpackage UnitTests
 * @copyright  Copyright (c) 2010-2014 Pádraic Brady (http://blog.astrumfutura.com)
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
 */

use Mockery\Adapter\Phpunit\MockeryTestCase;

class DemeterChainTest extends MockeryTestCase
{
    /** @var  Mockery\Mock $this->mock */
    private $mock;

    public function setUp()
    {
        $this->mock = $this->mock = Mockery::mock('stdClass')->shouldIgnoreMissing();
    }

    public function tearDown()
    {
        $this->mock->mockery_getContainer()->mockery_close();
    }

    public function testTwoChains()
    {
        $this->mock->shouldReceive('getElement->getFirst')
            ->once()
            ->andReturn('something');

        $this->mock->shouldReceive('getElement->getSecond')
            ->once()
            ->andReturn('somethingElse');

        $this->assertEquals(
            'something',
            $this->mock->getElement()->getFirst()
        );
        $this->assertEquals(
            'somethingElse',
            $this->mock->getElement()->getSecond()
        );
        $this->mock->mockery_getContainer()->mockery_close();
    }

    public function testTwoChainsWithExpectedParameters()
    {
        $this->mock->shouldReceive('getElement->getFirst')
            ->once()
            ->with('parameter')
            ->andReturn('something');

        $this->mock->shouldReceive('getElement->getSecond')
            ->once()
            ->with('secondParameter')
            ->andReturn('somethingElse');

        $this->assertEquals(
            'something',
            $this->mock->getElement()->getFirst('parameter')
        );
        $this->assertEquals(
            'somethingElse',
            $this->mock->getElement()->getSecond('secondParameter')
        );
        $this->mock->mockery_getContainer()->mockery_close();
    }

    public function testThreeChains()
    {
        $this->mock->shouldReceive('getElement->getFirst')
            ->once()
            ->andReturn('something');

        $this->mock->shouldReceive('getElement->getSecond')
            ->once()
            ->andReturn('somethingElse');

        $this->assertEquals(
            'something',
            $this->mock->getElement()->getFirst()
        );
        $this->assertEquals(
            'somethingElse',
            $this->mock->getElement()->getSecond()
        );
        $this->mock->shouldReceive('getElement->getFirst')
            ->once()
            ->andReturn('somethingNew');
        $this->assertEquals(
            'somethingNew',
            $this->mock->getElement()->getFirst()
        );
    }

    public function testManyChains()
    {
        $this->mock->shouldReceive('getElements->getFirst')
            ->once()
            ->andReturn('something');

        $this->mock->shouldReceive('getElements->getSecond')
            ->once()
            ->andReturn('somethingElse');

        $this->mock->getElements()->getFirst();
        $this->mock->getElements()->getSecond();
    }

    public function testTwoNotRelatedChains()
    {
        $this->mock->shouldReceive('getElement->getFirst')
            ->once()
            ->andReturn('something');

        $this->mock->shouldReceive('getOtherElement->getSecond')
            ->once()
            ->andReturn('somethingElse');

        $this->assertEquals(
            'somethingElse',
            $this->mock->getOtherElement()->getSecond()
        );
        $this->assertEquals(
            'something',
            $this->mock->getElement()->getFirst()
        );
    }

    public function testDemeterChain()
    {
        $this->mock->shouldReceive('getElement->getFirst')
            ->once()
            ->andReturn('somethingElse');

        $this->assertEquals('somethingElse', $this->mock->getElement()->getFirst());
    }

    public function testMultiLevelDemeterChain()
    {
        $this->mock->shouldReceive('levelOne->levelTwo->getFirst')
            ->andReturn('first');

        $this->mock->shouldReceive('levelOne->levelTwo->getSecond')
            ->andReturn('second');

        $this->assertEquals(
            'second',
            $this->mock->levelOne()->levelTwo()->getSecond()
        );
        $this->assertEquals(
            'first',
            $this->mock->levelOne()->levelTwo()->getFirst()
        );
    }
}
MockClassWithUnknownTypeHintTest.php000066400000002047151520664250013710 0ustar00<?php

/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mockery/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 */

namespace test\Mockery;

use Mockery\Adapter\Phpunit\MockeryTestCase;

class MockClassWithUnknownTypeHintTest extends MockeryTestCase
{
    protected function setUp()
    {
        $this->container = new \Mockery\Container;
    }

    protected function tearDown()
    {
        $this->container->mockery_close();
    }

    /** @test */
    public function itShouldSuccessfullyBuildTheMock()
    {
        $this->container->mock("test\Mockery\HasUnknownClassAsTypeHintOnMethod");
    }
}

class HasUnknownClassAsTypeHintOnMethod
{
    public function foo(\UnknownTestClass\Bar $bar)
    {
    }
}
MockingVariadicArgumentsTest.php000066400000002610151520664250013044 0ustar00<?php
/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mockery/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 *
 * @category   Mockery
 * @package    Mockery
 * @subpackage UnitTests
 * @copyright  Copyright (c) 2010-2014 Pádraic Brady (http://blog.astrumfutura.com)
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
 */

namespace test\Mockery;

use Mockery\Adapter\Phpunit\MockeryTestCase;

class MockingVariadicArgumentsTest extends MockeryTestCase
{

    public function setup()
    {
        $this->container = new \Mockery\Container;
    }

    public function teardown()
    {
        $this->container->mockery_close();
    }

    /** @test */
    public function shouldAllowMockingVariadicArguments()
    {
        $mock = $this->container->mock("test\Mockery\TestWithVariadicArguments");

        $mock->shouldReceive("foo")->andReturn("notbar");
        $this->assertEquals("notbar", $mock->foo());
    }
}


abstract class TestWithVariadicArguments
{
    public function foo(...$bar)
    {
        return $bar;
    }
}
AdhocTest.php000066400000005035151520664250007146 0ustar00<?php
/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mockery/blob/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 *
 * @category   Mockery
 * @package    Mockery
 * @subpackage UnitTests
 * @copyright  Copyright (c) 2010-2014 Pádraic Brady (http://blog.astrumfutura.com)
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
 */

use Mockery\Adapter\Phpunit\MockeryTestCase;

/**
 * Ad-hoc unit tests for various scenarios reported by users
 */
class Mockery_AdhocTest extends MockeryTestCase
{

    public function setup()
    {
        $this->container = new \Mockery\Container(\Mockery::getDefaultGenerator(), \Mockery::getDefaultLoader());
    }

    public function teardown()
    {
        $this->container->mockery_close();
    }

    public function testSimplestMockCreation()
    {
        $m = $this->container->mock('MockeryTest_NameOfExistingClass');
        $this->assertTrue($m instanceof MockeryTest_NameOfExistingClass);
    }

    public function testMockeryInterfaceForClass()
    {
        $m = $this->container->mock('SplFileInfo');
        $this->assertTrue($m instanceof \Mockery\MockInterface);
    }

    public function testMockeryInterfaceForNonExistingClass()
    {
        $m = $this->container->mock('ABC_IDontExist');
        $this->assertTrue($m instanceof \Mockery\MockInterface);
    }

    public function testMockeryInterfaceForInterface()
    {
        $m = $this->container->mock('MockeryTest_NameOfInterface');
        $this->assertTrue($m instanceof \Mockery\MockInterface);
    }

    public function testMockeryInterfaceForAbstract()
    {
        $m = $this->container->mock('MockeryTest_NameOfAbstract');
        $this->assertTrue($m instanceof \Mockery\MockInterface);
    }

    public function testInvalidCountExceptionThrowsRuntimeExceptionOnIllegalComparativeSymbol()
    {
        $this->setExpectedException('Mockery\Exception\RuntimeException');
        $e = new \Mockery\Exception\InvalidCountException;
        $e->setExpectedCountComparative('X');
    }
}

class MockeryTest_NameOfExistingClass
{
}

interface MockeryTest_NameOfInterface
{
    public function foo();
}

abstract class MockeryTest_NameOfAbstract
{
    abstract public function foo();
}
LoaderTest.php000066400000002545151520664250007341 0ustar00<?php
/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mockery/blob/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 *
 * @category   Mockery
 * @package    Mockery
 * @subpackage UnitTests
 * @copyright  Copyright (c) 2010-2014 Pádraic Brady (http://blog.astrumfutura.com)
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
 */

class Mockery_LoaderTest extends PHPUnit_Framework_TestCase
{

    public function setUp()
    {
        spl_autoload_unregister('\Mockery\Loader::loadClass');
    }

    public function testCallingRegisterRegistersSelfAsSplAutoloaderFunction()
    {
        require_once 'Mockery/Loader.php';
        $loader = new \Mockery\Loader;
        $loader->register();
        $expected = array($loader, 'loadClass');
        $this->assertTrue(in_array($expected, spl_autoload_functions()));
    }

    public function tearDown()
    {
        spl_autoload_unregister('\Mockery\Loader::loadClass');
        $loader = new \Mockery\Loader;
        $loader->register();
    }
}
_files/file.txt000066400000000000151520664250007463 0ustar00Fixtures/MethodWithNullableParameters.php000066400000002235151520664250014657 0ustar00<?php
/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mockery/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 *
 * @category   Mockery
 * @package    Mockery
 * @subpackage UnitTests
 * @copyright  Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
 */

namespace test\Mockery\Fixtures;

class MethodWithNullableParameters
{
    public function nonNullablePrimitive(string $a)
    {
    }

    public function nullablePrimitive(?string $a)
    {
    }

    public function nonNullableSelf(self $a)
    {
    }

    public function nullableSelf(?self $a)
    {
    }

    public function nonNullableClass(MethodWithNullableParameters $a)
    {
    }

    public function nullableClass(?MethodWithNullableParameters $a)
    {
    }
}
Fixtures/VoidMethod.php000066400000001433151520664250011141 0ustar00<?php
/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mockery/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 *
 * @category   Mockery
 * @package    Mockery
 * @subpackage UnitTests
 * @copyright  Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
 */

namespace test\Mockery\Fixtures;

interface VoidMethod
{
    public function foo(): void;
}
Fixtures/MethodWithNullableReturnType.php000066400000002545151520664250014701 0ustar00<?php
/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mockery/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 *
 * @category   Mockery
 * @package    Mockery
 * @subpackage UnitTests
 * @copyright  Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
 */

namespace test\Mockery\Fixtures;

use Mockery\Adapter\Phpunit\MockeryTestCase;

class MethodWithNullableReturnType extends MockeryTestCase
{
    public function nonNullablePrimitive() : string
    {
        return 'test';
    }

    public function nullablePrimitive() : ?string
    {
        return null;
    }

    public function nonNullableSelf() : self
    {
        return $this;
    }

    public function nullableSelf() : ?self
    {
        return null;
    }

    public function nonNullableClass() : MethodWithNullableReturnType
    {
        return $this;
    }

    public function nullableClass() : ?MethodWithNullableReturnType
    {
        return null;
    }
}
CompositeExpectation.php000066400000006302151520666110011431 0ustar00<?php
/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mockery/blob/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 *
 * @category   Mockery
 * @package    Mockery
 * @copyright  Copyright (c) 2010-2014 Pádraic Brady (http://blog.astrumfutura.com)
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
 */

namespace Mockery;

class CompositeExpectation implements ExpectationInterface
{

    /**
     * Stores an array of all expectations for this composite
     *
     * @var array
     */
    protected $_expectations = array();

    /**
     * Add an expectation to the composite
     *
     * @param \Mockery\Expectation|\Mockery\CompositeExpectation $expectation
     * @return void
     */
    public function add($expectation)
    {
        $this->_expectations[] = $expectation;
    }

    /**
     * @param mixed ...
     */
    public function andReturn()
    {
        return $this->__call(__FUNCTION__, func_get_args());
    }

    /**
     * Intercept any expectation calls and direct against all expectations
     *
     * @param string $method
     * @param array $args
     * @return self
     */
    public function __call($method, array $args)
    {
        foreach ($this->_expectations as $expectation) {
            call_user_func_array(array($expectation, $method), $args);
        }
        return $this;
    }

    /**
     * Return order number of the first expectation
     *
     * @return int
     */
    public function getOrderNumber()
    {
        reset($this->_expectations);
        $first = current($this->_expectations);
        return $first->getOrderNumber();
    }

    /**
     * Return the parent mock of the first expectation
     *
     * @return \Mockery\MockInterface
     */
    public function getMock()
    {
        reset($this->_expectations);
        $first = current($this->_expectations);
        return $first->getMock();
    }

    /**
     * Mockery API alias to getMock
     *
     * @return \Mockery\MockInterface
     */
    public function mock()
    {
        return $this->getMock();
    }

    /**
     * Starts a new expectation addition on the first mock which is the primary
     * target outside of a demeter chain
     *
     * @param mixed ...
     * @return \Mockery\Expectation
     */
    public function shouldReceive()
    {
        $args = func_get_args();
        reset($this->_expectations);
        $first = current($this->_expectations);
        return call_user_func_array(array($first->getMock(), 'shouldReceive'), $args);
    }

    /**
     * Return the string summary of this composite expectation
     *
     * @return string
     */
    public function __toString()
    {
        $return = '[';
        $parts = array();
        foreach ($this->_expectations as $exp) {
            $parts[] = (string) $exp;
        }
        $return .= implode(', ', $parts) . ']';
        return $return;
    }
}
MockInterface.php000066400000013361151520666110010000 0ustar00<?php
/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mockery/blob/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 *
 * @category   Mockery
 * @package    Mockery
 * @copyright  Copyright (c) 2010-2014 Pádraic Brady (http://blog.astrumfutura.com)
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
 */

namespace Mockery;

interface MockInterface
{

    /**
     * Alternative setup method to constructor
     *
     * @param \Mockery\Container $container
     * @param object $partialObject
     * @return void
     */
    public function mockery_init(\Mockery\Container $container = null, $partialObject = null);

    /**
     * Set expected method calls
     *
     * @param mixed ...
     * @return \Mockery\Expectation
     */
    public function shouldReceive();

    /**
     * Shortcut method for setting an expectation that a method should not be called.
     *
     * @param mixed ...
     * @return \Mockery\Expectation
     */
    public function shouldNotReceive();

    /**
     * Allows additional methods to be mocked that do not explicitly exist on mocked class
     * @param String $method name of the method to be mocked
     */
    public function shouldAllowMockingMethod($method);

    /**
     * Set mock to ignore unexpected methods and return Undefined class
     * @param mixed $returnValue the default return value for calls to missing functions on this mock
     * @return Mock
     */
    public function shouldIgnoreMissing($returnValue = null);

    /**
     * @return Mock
     */
    public function shouldAllowMockingProtectedMethods();

    /**
     * Set mock to defer unexpected methods to its parent if possible
     *
     * @return Mock
     */
    public function shouldDeferMissing();
    
    /**
     * Set mock to defer unexpected methods to its parent if possible
     *
     * @return Mock
     */
    public function makePartial();

    /**
     * @param $method
     * @param null $args
     * @return \Mockery\Expectation
     */
    public function shouldHaveReceived($method, $args = null);

    /**
     * @param $method
     * @param null $args
     * @return null
     */
    public function shouldNotHaveReceived($method, $args = null);


    /**
     * In the event shouldReceive() accepting an array of methods/returns
     * this method will switch them from normal expectations to default
     * expectations
     *
     * @return self
     */
    public function byDefault();

    /**
     * Capture calls to this mock and check against expectations
     *
     * @param string $method
     * @param array $args
     * @return mixed
     */
        /**
         * Unfortunately we need to allow type hinting agnostic __call()
         * definitions since any interface/class being mocked can go either
         * way.
         */
    //public function __call($method, array $args);

    /**
     * Iterate across all expectation directors and validate each
     *
     * @throws \Mockery\CountValidator\Exception
     * @return void
     */
    public function mockery_verify();

    /**
     * Tear down tasks for this mock
     *
     * @return void
     */
    public function mockery_teardown();

    /**
     * Fetch the next available allocation order number
     *
     * @return int
     */
    public function mockery_allocateOrder();

    /**
     * Set ordering for a group
     *
     * @param mixed $group
     * @param int $order
     */
    public function mockery_setGroup($group, $order);

    /**
     * Fetch array of ordered groups
     *
     * @return array
     */
    public function mockery_getGroups();

    /**
     * Set current ordered number
     *
     * @param int $order
     */
    public function mockery_setCurrentOrder($order);

    /**
     * Get current ordered number
     *
     * @return int
     */
    public function mockery_getCurrentOrder();

    /**
     * Validate the current mock's ordering
     *
     * @param string $method
     * @param int $order
     * @throws \Mockery\Exception
     * @return void
     */
    public function mockery_validateOrder($method, $order);

    /**
     * Gets the count of expectations for this mock
     *
     * @return int
     */
    public function mockery_getExpectationCount();

    /**
     * Return the expectations director for the given method
     *
     * @var string $method
     * @return \Mockery\ExpectationDirector|null
     */
    public function mockery_setExpectationsFor($method, \Mockery\ExpectationDirector $director);

    /**
     * Return the expectations director for the given method
     *
     * @var string $method
     * @return \Mockery\ExpectationDirector|null
     */
    public function mockery_getExpectationsFor($method);

    /**
     * Find an expectation matching the given method and arguments
     *
     * @var string $method
     * @var array $args
     * @return \Mockery\Expectation|null
     */
    public function mockery_findExpectation($method, array $args);

    /**
     * Return the container for this mock
     *
     * @return \Mockery\Container
     */
    public function mockery_getContainer();

    /**
     * Return the name for this mock
     *
     * @return string
     */
    public function mockery_getName();

    /**
     * @return array
     */
    public function mockery_getMockableProperties();

    /**
     * @return string[]
     */
    public function mockery_getMockableMethods();

    /**
     * @return bool
     */
    public function mockery_isAnonymous();
}
Loader.php000066400000011064151520666110006472 0ustar00<?php
/**
 * SplClassLoader implementation that implements the technical interoperability
 * standards for PHP 5.3 namespaces and class names.
 *
 * http://groups.google.com/group/php-standards/web/final-proposal
 *
 *     // Example which loads classes for the Doctrine Common package in the
 *     // Doctrine\Common namespace.
 *     $classLoader = new SplClassLoader('Doctrine\Common', '/path/to/doctrine');
 *     $classLoader->register();
 *
 * @author Jonathan H. Wage <jonwage@gmail.com>
 * @author Roman S. Borschel <roman@code-factory.org>
 * @author Matthew Weier O'Phinney <matthew@zend.com>
 * @author Kris Wallsmith <kris.wallsmith@gmail.com>
 * @author Fabien Potencier <fabien.potencier@symfony-project.org>
 */

namespace Mockery;

class Loader
{
    private $_fileExtension = '.php';
    private $_namespace;
    private $_includePath;
    private $_namespaceSeparator = '\\';

    /**
     * Creates a new <tt>Loader</tt> that loads classes of the
     * specified namespace.
     *
     * @param string $ns The namespace to use.
     */
    public function __construct($ns = 'Mockery', $includePath = null)
    {
        $this->_namespace = $ns;
        $this->_includePath = $includePath;
    }

    /**
     * Sets the namespace separator used by classes in the namespace of this class loader.
     *
     * @param string $sep The separator to use.
     */
    public function setNamespaceSeparator($sep)
    {
        $this->_namespaceSeparator = $sep;
    }

    /**
     * Gets the namespace seperator used by classes in the namespace of this class loader.
     *
     * @return void
     */
    public function getNamespaceSeparator()
    {
        return $this->_namespaceSeparator;
    }

    /**
     * Sets the base include path for all class files in the namespace of this class loader.
     *
     * @param string $includePath
     */
    public function setIncludePath($includePath)
    {
        $this->_includePath = $includePath;
    }

    /**
     * Gets the base include path for all class files in the namespace of this class loader.
     *
     * @return string $includePath
     */
    public function getIncludePath()
    {
        return $this->_includePath;
    }

    /**
     * Sets the file extension of class files in the namespace of this class loader.
     *
     * @param string $fileExtension
     */
    public function setFileExtension($fileExtension)
    {
        $this->_fileExtension = $fileExtension;
    }

    /**
     * Gets the file extension of class files in the namespace of this class loader.
     *
     * @return string $fileExtension
     */
    public function getFileExtension()
    {
        return $this->_fileExtension;
    }

    /**
     * Installs this class loader on the SPL autoload stack.
     *
     * @param bool $prepend If true, prepend autoloader on the autoload stack
     */
    public function register($prepend = false)
    {
        spl_autoload_register(array($this, 'loadClass'), true, $prepend);
    }

    /**
     * Uninstalls this class loader from the SPL autoloader stack.
     */
    public function unregister()
    {
        spl_autoload_unregister(array($this, 'loadClass'));
    }

    /**
     * Loads the given class or interface.
     *
     * @param string $className The name of the class to load.
     * @return void
     */
    public function loadClass($className)
    {
        if ($className === 'Mockery') {
            require $this->getFullPath('Mockery.php');
            return;
        }
        if (null === $this->_namespace
        || $this->_namespace.$this->_namespaceSeparator === substr($className, 0, strlen($this->_namespace.$this->_namespaceSeparator))) {
            $fileName = '';
            $namespace = '';
            if (false !== ($lastNsPos = strripos($className, $this->_namespaceSeparator))) {
                $namespace = substr($className, 0, $lastNsPos);
                $className = substr($className, $lastNsPos + 1);
                $fileName = str_replace($this->_namespaceSeparator, DIRECTORY_SEPARATOR, $namespace) . DIRECTORY_SEPARATOR;
            }
            $fileName .= str_replace('_', DIRECTORY_SEPARATOR, $className) . $this->_fileExtension;
            require $this->getFullPath($fileName);
        }
    }

    /**
     * Returns full path for $fileName if _includePath is set, or leaves as-is for PHP's internal search in 'require'.
     *
     * @param string $fileName relative to include path.
     * @return string
     */
    private function getFullPath($fileName)
    {
        return ($this->_includePath !== null ? $this->_includePath . DIRECTORY_SEPARATOR : '') . $fileName;
    }
}
ReceivedMethodCalls.php000066400000001212151520666110011124 0ustar00<?php

namespace Mockery;

class ReceivedMethodCalls
{
    private $methodCalls = array();
    
    public function push(MethodCall $methodCall)
    {
        $this->methodCalls[] = $methodCall;
    }

    public function verify(Expectation $expectation)
    {
        foreach ($this->methodCalls as $methodCall) {
            if ($methodCall->getMethod() !== $expectation->getName()) {
                continue;
            }

            if (!$expectation->matchArgs($methodCall->getArgs())) {
                continue;
            }

            $expectation->verifyCall($methodCall->getArgs());
        }

        $expectation->verify();
    }
}
MethodCall.php000066400000000545151520666110007302 0ustar00<?php

namespace Mockery;

class MethodCall
{
    private $method;
    private $args;

    public function __construct($method, $args)
    {
        $this->method = $method;
        $this->args = $args;
    }

    public function getMethod()
    {
        return $this->method;
    }

    public function getArgs()
    {
        return $this->args;
    }
}
Loader/RequireLoader.php000066400000001044151520666110011232 0ustar00<?php

namespace Mockery\Loader;

use Mockery\Generator\MockDefinition;
use Mockery\Loader\Loader;

class RequireLoader implements Loader
{
    protected $path;

    public function __construct($path)
    {
        $this->path = $path;
    }

    public function load(MockDefinition $definition)
    {
        if (class_exists($definition->getClassName(), false)) {
            return;
        }

        $tmpfname = tempnam($this->path, "Mockery");
        file_put_contents($tmpfname, $definition->getCode());

        require $tmpfname;
    }
}
Loader/Loader.php000066400000000224151520666110007674 0ustar00<?php

namespace Mockery\Loader;

use Mockery\Generator\MockDefinition;

interface Loader
{
    public function load(MockDefinition $definition);
}
Loader/EvalLoader.php000066400000000530151520666110010504 0ustar00<?php

namespace Mockery\Loader;

use Mockery\Generator\MockDefinition;
use Mockery\Loader\Loader;

class EvalLoader implements Loader
{
    public function load(MockDefinition $definition)
    {
        if (class_exists($definition->getClassName(), false)) {
            return;
        }

        eval("?>" . $definition->getCode());
    }
}
Adapter/Phpunit/TestListener.php000066400000005751151520666110012726 0ustar00<?php
/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mockery/blob/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 *
 * @category   Mockery
 * @package    Mockery
 * @copyright  Copyright (c) 2010-2014 Pádraic Brady (http://blog.astrumfutura.com)
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
 */

namespace Mockery\Adapter\Phpunit;

class TestListener implements \PHPUnit_Framework_TestListener
{

    /**
     * After each test, perform Mockery verification tasks and cleanup the
     * statically stored Mockery container for the next test.
     *
     * @param  PHPUnit_Framework_Test $test
     * @param  float                  $time
     */
    public function endTest(\PHPUnit_Framework_Test $test, $time)
    {
        try {
            $container = \Mockery::getContainer();
            // check addToAssertionCount is important to avoid mask test errors
            if ($container != null && method_exists($test, 'addToAssertionCount')) {
                $expectation_count = $container->mockery_getExpectationCount();
                $test->addToAssertionCount($expectation_count);
            }
            \Mockery::close();
        } catch (\Exception $e) {
            $result = $test->getTestResultObject();
            $result->addError($test, $e, $time);
        }
    }

    /**
     * Add Mockery files to PHPUnit's blacklist so they don't showup on coverage reports
     */
    public function startTestSuite(\PHPUnit_Framework_TestSuite $suite)
    {
        if (class_exists('\\PHP_CodeCoverage_Filter')
        && method_exists('\\PHP_CodeCoverage_Filter', 'getInstance')) {
            \PHP_CodeCoverage_Filter::getInstance()->addDirectoryToBlacklist(
                 __DIR__.'/../../../Mockery/', '.php', '', 'PHPUNIT'
            );

            \PHP_CodeCoverage_Filter::getInstance()->addFileToBlacklist(__DIR__.'/../../../Mockery.php', 'PHPUNIT');
        }
    }
    /**
     *  The Listening methods below are not required for Mockery
     */
    public function addError(\PHPUnit_Framework_Test $test, \Exception $e, $time)
    {
    }

    public function addFailure(\PHPUnit_Framework_Test $test, \PHPUnit_Framework_AssertionFailedError $e, $time)
    {
    }

    public function addIncompleteTest(\PHPUnit_Framework_Test $test, \Exception $e, $time)
    {
    }

    public function addSkippedTest(\PHPUnit_Framework_Test $test, \Exception $e, $time)
    {
    }

    public function addRiskyTest(\PHPUnit_Framework_Test $test, \Exception $e, $time)
    {
    }

    public function endTestSuite(\PHPUnit_Framework_TestSuite $suite)
    {
    }

    public function startTest(\PHPUnit_Framework_Test $test)
    {
    }
}
Adapter/Phpunit/MockeryPHPUnitIntegration.php000066400000001410151520666110015312 0ustar00<?php
namespace Mockery\Adapter\Phpunit;

/**
 * Integrates Mockery into PHPUnit. Ensures Mockery expectations are verified
 * for each test and are included by the assertion counter.
 */
trait MockeryPHPUnitIntegration
{
    /**
     * Performs assertions shared by all tests of a test case. This method is
     * called before execution of a test ends and before the tearDown method.
     */
    protected function assertPostConditions()
    {
        parent::assertPostConditions();

        // Add Mockery expectations to assertion count.
        if (($container = \Mockery::getContainer()) !== null) {
            $this->addToAssertionCount($container->mockery_getExpectationCount());
        }

        // Verify Mockery expectations.
        \Mockery::close();
    }
}
Adapter/Phpunit/MockeryTestCase.php000066400000001237151520666110013341 0ustar00<?php

namespace Mockery\Adapter\Phpunit;

use Mockery;

abstract class MockeryTestCase extends \PHPUnit_Framework_TestCase
{
    protected function assertPostConditions()
    {
        $this->addMockeryExpectationsToAssertionCount();
        $this->closeMockery();

        parent::assertPostConditions();
    }

    protected function addMockeryExpectationsToAssertionCount()
    {
        $container = Mockery::getContainer();
        if ($container != null) {
            $count = $container->mockery_getExpectationCount();
            $this->addToAssertionCount($count);
        }
    }

    protected function closeMockery()
    {
        Mockery::close();
    }
}
Recorder.php000066400000005760151520666110007037 0ustar00<?php
/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mockery/blob/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 *
 * @category   Mockery
 * @package    Mockery
 * @copyright  Copyright (c) 2010-2014 Pádraic Brady (http://blog.astrumfutura.com)
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
 */

namespace Mockery;

class Recorder
{

    /**
     * Mock object on which all recorded interactions will be set as
     * expectations
     *
     * @var object
     */
    protected $_mock = null;

    /**
     * The subject object whose interactions are being recorded
     *
     * @var object
     */
    protected $_subject = null;

    /**
     * Flag indicating whether the recording should maintain a strict adherence
     * to the recorded interactions, i.e. the usual Mockery flexibility is
     * suspended, ordering is enforced, and arguments received are set as
     * exact requirements.
     *
     * @var bool
     */
    protected $_strict = false;

    /**
     * Construct accepting the mock object on which expectations are to be
     * recorded. The second parameter is the subject object, passed into
     * a \Mockery::mock() call in the same way as a partial mock requires.
     *
     * @param \Mockery\MockInterface $mock
     * @param object $subject
     * @return void
     */
    public function __construct(\Mockery\MockInterface $mock, $subject)
    {
        $this->_mock = $mock;
        $this->_subject = $subject;
    }

    /**
     * Sets the recorded into strict mode where method calls are more strictly
     * matched against the argument and call count and ordering is also
     * set as enforceable.
     *
     * @return void
     */
    public function shouldBeStrict()
    {
        $this->_strict = true;
    }

    /**
     * Intercept all calls on the subject, and use the call details to create
     * a new expectation. The actual return value is then returned after being
     * recorded.
     *
     * @param string $method
     * @param array $args
     * @return mixed
     */
    public function __call($method, array $args)
    {
        $return = call_user_func_array(array($this->_subject, $method), $args);
        $expectation = $this->_mock->shouldReceive($method)->andReturn($return);
        if ($this->_strict) {
            $exactArgs = array();
            foreach ($args as $arg) {
                $exactArgs[] = \Mockery::mustBe($arg);
            }
            $expectation->once()->ordered();
            call_user_func_array(array($expectation, 'with'), $exactArgs);
        } else {
            call_user_func_array(array($expectation, 'with'), $args);
        }
        return $return;
    }
}
Instantiator.php000066400000015331151520666110007744 0ustar00<?php
/*
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * This software consists of voluntary contributions made by many individuals
 * and is licensed under the MIT license. For more information, see
 * <http://www.doctrine-project.org>.
 */

namespace Mockery;

use Closure;
use ReflectionClass;
use UnexpectedValueException;
use InvalidArgumentException;

/**
 * This is a trimmed down version of https://github.com/doctrine/instantiator,
 * basically without the caching
 *
 * @author Marco Pivetta <ocramius@gmail.com>
 */
final class Instantiator
{
    /**
     * Markers used internally by PHP to define whether {@see \unserialize} should invoke
     * the method {@see \Serializable::unserialize()} when dealing with classes implementing
     * the {@see \Serializable} interface.
     */
    const SERIALIZATION_FORMAT_USE_UNSERIALIZER   = 'C';
    const SERIALIZATION_FORMAT_AVOID_UNSERIALIZER = 'O';

    /**
     * {@inheritDoc}
     */
    public function instantiate($className)
    {
        $factory    = $this->buildFactory($className);
        $instance   = $factory();
        $reflection = new ReflectionClass($instance);

        return $instance;
    }

    /**
     * @internal
     * @private
     *
     * Builds a {@see \Closure} capable of instantiating the given $className without
     * invoking its constructor.
     * This method is only exposed as public because of PHP 5.3 compatibility. Do not
     * use this method in your own code
     *
     * @param string $className
     *
     * @return Closure
     */
    public function buildFactory($className)
    {
        $reflectionClass = $this->getReflectionClass($className);

        if ($this->isInstantiableViaReflection($reflectionClass)) {
            return function () use ($reflectionClass) {
                return $reflectionClass->newInstanceWithoutConstructor();
            };
        }

        $serializedString = sprintf(
            '%s:%d:"%s":0:{}',
            $this->getSerializationFormat($reflectionClass),
            strlen($className),
            $className
        );

        $this->attemptInstantiationViaUnSerialization($reflectionClass, $serializedString);

        return function () use ($serializedString) {
            return unserialize($serializedString);
        };
    }

    /**
     * @param string $className
     *
     * @return ReflectionClass
     *
     * @throws InvalidArgumentException
     */
    private function getReflectionClass($className)
    {
        if (! class_exists($className)) {
            throw new InvalidArgumentException("Class:$className does not exist");
        }

        $reflection = new ReflectionClass($className);

        if ($reflection->isAbstract()) {
            throw new InvalidArgumentException("Class:$className is an abstract class");
        }

        return $reflection;
    }

    /**
     * @param ReflectionClass $reflectionClass
     * @param string          $serializedString
     *
     * @throws UnexpectedValueException
     *
     * @return void
     */
    private function attemptInstantiationViaUnSerialization(ReflectionClass $reflectionClass, $serializedString)
    {
        set_error_handler(function ($code, $message, $file, $line) use ($reflectionClass, & $error) {
            $msg = sprintf(
                'Could not produce an instance of "%s" via un-serialization, since an error was triggered in file "%s" at line "%d"',
                $reflectionClass->getName(),
                $file,
                $line
            );

            $error = new UnexpectedValueException($msg, 0, new \Exception($message, $code));
        });

        try {
            unserialize($serializedString);
        } catch (\Exception $exception) {
            restore_error_handler();

            throw new UnexpectedValueException("An exception was raised while trying to instantiate an instance of \"{$reflectionClass->getName()}\" via un-serialization", 0, $exception);
        }

        restore_error_handler();

        if ($error) {
            throw $error;
        }
    }

    /**
     * @param ReflectionClass $reflectionClass
     *
     * @return bool
     */
    private function isInstantiableViaReflection(ReflectionClass $reflectionClass)
    {
        if (\PHP_VERSION_ID >= 50600) {
            return ! ($reflectionClass->isInternal() && $reflectionClass->isFinal());
        }

        return \PHP_VERSION_ID >= 50400 && ! $this->hasInternalAncestors($reflectionClass);
    }

    /**
     * Verifies whether the given class is to be considered internal
     *
     * @param ReflectionClass $reflectionClass
     *
     * @return bool
     */
    private function hasInternalAncestors(ReflectionClass $reflectionClass)
    {
        do {
            if ($reflectionClass->isInternal()) {
                return true;
            }
        } while ($reflectionClass = $reflectionClass->getParentClass());

        return false;
    }

    /**
     * Verifies if the given PHP version implements the `Serializable` interface serialization
     * with an incompatible serialization format. If that's the case, use serialization marker
     * "C" instead of "O".
     *
     * @link http://news.php.net/php.internals/74654
     *
     * @param ReflectionClass $reflectionClass
     *
     * @return string the serialization format marker, either self::SERIALIZATION_FORMAT_USE_UNSERIALIZER
     *                or self::SERIALIZATION_FORMAT_AVOID_UNSERIALIZER
     */
    private function getSerializationFormat(ReflectionClass $reflectionClass)
    {
        if ($this->isPhpVersionWithBrokenSerializationFormat()
            && $reflectionClass->implementsInterface('Serializable')
        ) {
            return self::SERIALIZATION_FORMAT_USE_UNSERIALIZER;
        }

        return self::SERIALIZATION_FORMAT_AVOID_UNSERIALIZER;
    }

    /**
     * Checks whether the current PHP runtime uses an incompatible serialization format
     *
     * @return bool
     */
    private function isPhpVersionWithBrokenSerializationFormat()
    {
        return PHP_VERSION_ID === 50429 || PHP_VERSION_ID === 50513;
    }
}
ExpectationInterface.php000066400000001703151520666110011367 0ustar00<?php

/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mockery/blob/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 *
 * @category   Mockery
 * @package    Mockery
 * @copyright  Copyright (c) 2010-2014 Pádraic Brady (http://blog.astrumfutura.com)
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
 */
namespace Mockery;

interface ExpectationInterface
{
    /**
     * @return int
     */
    public function getOrderNumber();

    /**
     * @return MockInterface
     */
    public function getMock();

    /**
     * @return self
     */
    public function andReturn();
}
ExpectationDirector.php000066400000012245151520666110011245 0ustar00<?php
/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mockery/blob/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 *
 * @category   Mockery
 * @package    Mockery
 * @copyright  Copyright (c) 2010-2014 Pádraic Brady (http://blog.astrumfutura.com)
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
 */

namespace Mockery;

class ExpectationDirector
{

    /**
     * Method name the director is directing
     *
     * @var string
     */
    protected $_name = null;

    /**
     * Mock object the director is attached to
     *
     * @var \Mockery\MockInterface
     */
    protected $_mock = null;

    /**
     * Stores an array of all expectations for this mock
     *
     * @var array
     */
    protected $_expectations = array();

    /**
     * The expected order of next call
     *
     * @var int
     */
    protected $_expectedOrder = null;

    /**
     * Stores an array of all default expectations for this mock
     *
     * @var array
     */
    protected $_defaults = array();

    /**
     * Constructor
     *
     * @param string $name
     * @param \Mockery\MockInterface $mock
     */
    public function __construct($name, \Mockery\MockInterface $mock)
    {
        $this->_name = $name;
        $this->_mock = $mock;
    }

    /**
     * Add a new expectation to the director
     *
     * @param Mutateme\Expectation $expectation
     */
    public function addExpectation(\Mockery\Expectation $expectation)
    {
        $this->_expectations[] = $expectation;
    }

    /**
     * Handle a method call being directed by this instance
     *
     * @param array $args
     * @return mixed
     */
    public function call(array $args)
    {
        $expectation = $this->findExpectation($args);
        if (is_null($expectation)) {
            $exception = new \Mockery\Exception\NoMatchingExpectationException(
                'No matching handler found for '
                . $this->_mock->mockery_getName() . '::'
                . \Mockery::formatArgs($this->_name, $args)
                . '. Either the method was unexpected or its arguments matched'
                . ' no expected argument list for this method'
                . PHP_EOL . PHP_EOL
                . \Mockery::formatObjects($args)
            );
            $exception->setMock($this->_mock)
                ->setMethodName($this->_name)
                ->setActualArguments($args);
            throw $exception;
        }
        return $expectation->verifyCall($args);
    }

    /**
     * Verify all expectations of the director
     *
     * @throws \Mockery\CountValidator\Exception
     * @return void
     */
    public function verify()
    {
        if (!empty($this->_expectations)) {
            foreach ($this->_expectations as $exp) {
                $exp->verify();
            }
        } else {
            foreach ($this->_defaults as $exp) {
                $exp->verify();
            }
        }
    }

    /**
     * Attempt to locate an expectation matching the provided args
     *
     * @param array $args
     * @return mixed
     */
    public function findExpectation(array $args)
    {
        if (!empty($this->_expectations)) {
            return $this->_findExpectationIn($this->_expectations, $args);
        } else {
            return $this->_findExpectationIn($this->_defaults, $args);
        }
    }

    /**
     * Make the given expectation a default for all others assuming it was
     * correctly created last
     *
     * @param \Mockery\Expectation
     */
    public function makeExpectationDefault(\Mockery\Expectation $expectation)
    {
        $last = end($this->_expectations);
        if ($last === $expectation) {
            array_pop($this->_expectations);
            array_unshift($this->_defaults, $expectation);
        } else {
            throw new \Mockery\Exception(
                'Cannot turn a previously defined expectation into a default'
            );
        }
    }

    /**
     * Search current array of expectations for a match
     *
     * @param array $expectations
     * @param array $args
     * @return mixed
     */
    protected function _findExpectationIn(array $expectations, array $args)
    {
        foreach ($expectations as $exp) {
            if ($exp->matchArgs($args) && $exp->isEligible()) {
                return $exp;
            }
        }
        foreach ($expectations as $exp) {
            if ($exp->matchArgs($args)) {
                return $exp;
            }
        }
    }

    /**
     * Return all expectations assigned to this director
     *
     * @return array
     */
    public function getExpectations()
    {
        return $this->_expectations;
    }

    /**
     * Return the number of expectations assigned to this director.
     *
     * @return int
     */
    public function getExpectationCount()
    {
        return count($this->getExpectations());
    }
}
Configuration.php000066400000007237151520666110010102 0ustar00<?php
/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mockery/blob/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 *
 * @category   Mockery
 * @package    Mockery
 * @copyright  Copyright (c) 2010-2014 Pádraic Brady (http://blog.astrumfutura.com)
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
 */

namespace Mockery;

class Configuration
{

    /**
     * Boolean assertion of whether we can mock methods which do not actually
     * exist for the given class or object (ignored for unreal mocks)
     *
     * @var bool
     */
    protected $_allowMockingNonExistentMethod = true;

    /**
     * Boolean assertion of whether we ignore unnecessary mocking of methods,
     * i.e. when method expectations are made, set using a zeroOrMoreTimes()
     * constraint, and then never called. Essentially such expectations are
     * not required and are just taking up test space.
     *
     * @var bool
     */
    protected $_allowMockingMethodsUnnecessarily = true;

    /**
     * Parameter map for use with PHP internal classes.
     *
     * @var array
     */
    protected $_internalClassParamMap = array();

    /**
     * Set boolean to allow/prevent mocking of non-existent methods
     *
     * @param bool
     */
    public function allowMockingNonExistentMethods($flag = true)
    {
        $this->_allowMockingNonExistentMethod = (bool) $flag;
    }

    /**
     * Return flag indicating whether mocking non-existent methods allowed
     *
     * @return bool
     */
    public function mockingNonExistentMethodsAllowed()
    {
        return $this->_allowMockingNonExistentMethod;
    }

    /**
     * Set boolean to allow/prevent unnecessary mocking of methods
     *
     * @param bool
     */
    public function allowMockingMethodsUnnecessarily($flag = true)
    {
        $this->_allowMockingMethodsUnnecessarily = (bool) $flag;
    }

    /**
     * Return flag indicating whether mocking non-existent methods allowed
     *
     * @return bool
     */
    public function mockingMethodsUnnecessarilyAllowed()
    {
        return $this->_allowMockingMethodsUnnecessarily;
    }

    /**
     * Set a parameter map (array of param signature strings) for the method
     * of an internal PHP class.
     *
     * @param string $class
     * @param string $method
     * @param array $map
     */
    public function setInternalClassMethodParamMap($class, $method, array $map)
    {
        if (!isset($this->_internalClassParamMap[strtolower($class)])) {
            $this->_internalClassParamMap[strtolower($class)] = array();
        }
        $this->_internalClassParamMap[strtolower($class)][strtolower($method)] = $map;
    }

    /**
     * Remove all overriden parameter maps from internal PHP classes.
     */
    public function resetInternalClassMethodParamMaps()
    {
        $this->_internalClassParamMap = array();
    }

    /**
     * Get the parameter map of an internal PHP class method
     *
     * @return array
     */
    public function getInternalClassMethodParamMap($class, $method)
    {
        if (isset($this->_internalClassParamMap[strtolower($class)][strtolower($method)])) {
            return $this->_internalClassParamMap[strtolower($class)][strtolower($method)];
        }
    }

    public function getInternalClassMethodParamMaps()
    {
        return $this->_internalClassParamMap;
    }
}
Undefined.php000066400000002220151520666110007157 0ustar00<?php
/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mockery/blob/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 *
 * @category   Mockery
 * @package    Mockery
 * @copyright  Copyright (c) 2010-2014 Pádraic Brady (http://blog.astrumfutura.com)
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
 */

namespace Mockery;

class Undefined
{

    /**
     * Call capturing to merely return this same object.
     *
     * @param string $method
     * @param array $args
     * @return self
     */
    public function __call($method, array $args)
    {
        return $this;
    }

    /**
     * Return a string, avoiding E_RECOVERABLE_ERROR
     *
     * @return string
     */
    public function __toString()
    {
        return __CLASS__ . ":" . spl_object_hash($this);
    }
}
VerificationDirector.php000066400000004625151520666110011407 0ustar00<?php

namespace Mockery;

class VerificationDirector
{
    private $receivedMethodCalls;
    private $expectation;

    public function __construct(ReceivedMethodCalls $receivedMethodCalls, VerificationExpectation $expectation)
    {
        $this->receivedMethodCalls = $receivedMethodCalls;
        $this->expectation = $expectation;
    }

    public function verify()
    {
        return $this->receivedMethodCalls->verify($this->expectation);
    }

    public function with()
    {
        return $this->cloneApplyAndVerify("with", func_get_args());
    }

    public function withArgs(array $args)
    {
        return $this->cloneApplyAndVerify("withArgs", array($args));
    }

    public function withNoArgs()
    {
        return $this->cloneApplyAndVerify("withNoArgs", array());
    }

    public function withAnyArgs()
    {
        return $this->cloneApplyAndVerify("withAnyArgs", array());
    }

    public function times($limit = null)
    {
        return $this->cloneWithoutCountValidatorsApplyAndVerify("times", array($limit));
    }

    public function once()
    {
        return $this->cloneWithoutCountValidatorsApplyAndVerify("once", array());
    }

    public function twice()
    {
        return $this->cloneWithoutCountValidatorsApplyAndVerify("twice", array());
    }

    public function atLeast()
    {
        return $this->cloneWithoutCountValidatorsApplyAndVerify("atLeast", array());
    }

    public function atMost()
    {
        return $this->cloneWithoutCountValidatorsApplyAndVerify("atMost", array());
    }

    public function between($minimum, $maximum)
    {
        return $this->cloneWithoutCountValidatorsApplyAndVerify("between", array($minimum, $maximum));
    }

    protected function cloneWithoutCountValidatorsApplyAndVerify($method, $args)
    {
        $expectation = clone $this->expectation;
        $expectation->clearCountValidators();
        call_user_func_array(array($expectation, $method), $args);
        $director = new VerificationDirector($this->receivedMethodCalls, $expectation);
        $director->verify();
        return $director;
    }

    protected function cloneApplyAndVerify($method, $args)
    {
        $expectation = clone $this->expectation;
        call_user_func_array(array($expectation, $method), $args);
        $director = new VerificationDirector($this->receivedMethodCalls, $expectation);
        $director->verify();
        return $director;
    }
}
Exception/NoMatchingExpectationException.php000066400000003062151520666110015333 0ustar00<?php
/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mockery/blob/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 *
 * @category   Mockery
 * @package    Mockery
 * @copyright  Copyright (c) 2010-2014 Pádraic Brady (http://blog.astrumfutura.com)
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
 */

namespace Mockery\Exception;

use Mockery;

class NoMatchingExpectationException extends Mockery\Exception
{

    protected $method = null;

    protected $actual = array();

    protected $mockObject = null;

    public function setMock(Mockery\MockInterface $mock)
    {
        $this->mockObject = $mock;
        return $this;
    }

    public function setMethodName($name)
    {
        $this->method = $name;
        return $this;
    }

    public function setActualArguments($count)
    {
        $this->actual = $count;
        return $this;
    }

    public function getMock()
    {
        return $this->mockObject;
    }

    public function getMethodName()
    {
        return $this->method;
    }

    public function getActualArguments()
    {
        return $this->actual;
    }

    public function getMockName()
    {
        return $this->getMock()->mockery_getName();
    }
}
Exception/InvalidCountException.php000066400000004445151520666110013505 0ustar00<?php
/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mockery/blob/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 *
 * @category   Mockery
 * @package    Mockery
 * @copyright  Copyright (c) 2010-2014 Pádraic Brady (http://blog.astrumfutura.com)
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
 */

namespace Mockery\Exception;

use Mockery;
use Mockery\Exception\RuntimeException;

class InvalidCountException extends Mockery\CountValidator\Exception
{

    protected $method = null;

    protected $expected = 0;

    protected $expectedComparative = '<=';

    protected $actual = null;

    protected $mockObject = null;

    public function setMock(Mockery\MockInterface $mock)
    {
        $this->mockObject = $mock;
        return $this;
    }

    public function setMethodName($name)
    {
        $this->method = $name;
        return $this;
    }

    public function setActualCount($count)
    {
        $this->actual = $count;
        return $this;
    }

    public function setExpectedCount($count)
    {
        $this->expected = $count;
        return $this;
    }

    public function setExpectedCountComparative($comp)
    {
        if (!in_array($comp, array('=', '>', '<', '>=', '<='))) {
            throw new RuntimeException(
                'Illegal comparative for expected call counts set: ' . $comp
            );
        }
        $this->expectedComparative = $comp;
        return $this;
    }

    public function getMock()
    {
        return $this->mockObject;
    }

    public function getMethodName()
    {
        return $this->method;
    }

    public function getActualCount()
    {
        return $this->actual;
    }

    public function getExpectedCount()
    {
        return $this->expected;
    }

    public function getMockName()
    {
        return $this->getMock()->mockery_getName();
    }

    public function getExpectedCountComparative()
    {
        return $this->expectedComparative;
    }
}
Exception/RuntimeException.php000066400000001367151520666110012531 0ustar00<?php
/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mockery/blob/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 *
 * @category   Mockery
 * @package    Mockery
 * @copyright  Copyright (c) 2014 Pádraic Brady (http://blog.astrumfutura.com)
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
 */

namespace Mockery\Exception;

class RuntimeException extends \Exception
{
}
Exception/InvalidOrderException.php000066400000003402151520666110013460 0ustar00<?php
/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mockery/blob/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 *
 * @category   Mockery
 * @package    Mockery
 * @copyright  Copyright (c) 2010-2014 Pádraic Brady (http://blog.astrumfutura.com)
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
 */

namespace Mockery\Exception;

use Mockery;

class InvalidOrderException extends Mockery\Exception
{

    protected $method = null;

    protected $expected = 0;

    protected $actual = null;

    protected $mockObject = null;

    public function setMock(Mockery\MockInterface $mock)
    {
        $this->mockObject = $mock;
        return $this;
    }

    public function setMethodName($name)
    {
        $this->method = $name;
        return $this;
    }

    public function setActualOrder($count)
    {
        $this->actual = $count;
        return $this;
    }

    public function setExpectedOrder($count)
    {
        $this->expected = $count;
        return $this;
    }

    public function getMock()
    {
        return $this->mockObject;
    }

    public function getMethodName()
    {
        return $this->method;
    }

    public function getActualOrder()
    {
        return $this->actual;
    }

    public function getExpectedOrder()
    {
        return $this->expected;
    }

    public function getMockName()
    {
        return $this->getMock()->mockery_getName();
    }
}
CountValidator/Exact.php000066400000003174151520666110011271 0ustar00<?php
/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mockery/blob/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 *
 * @category   Mockery
 * @package    Mockery
 * @copyright  Copyright (c) 2010-2014 Pádraic Brady (http://blog.astrumfutura.com)
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
 */

namespace Mockery\CountValidator;

use Mockery;

class Exact extends CountValidatorAbstract
{

    /**
     * Validate the call count against this validator
     *
     * @param int $n
     * @return bool
     */
    public function validate($n)
    {
        if ($this->_limit !== $n) {
            $exception = new Mockery\Exception\InvalidCountException(
                'Method ' . (string) $this->_expectation
                . ' from ' . $this->_expectation->getMock()->mockery_getName()
                . ' should be called' . PHP_EOL
                . ' exactly ' . $this->_limit . ' times but called ' . $n
                . ' times.'
            );
            $exception->setMock($this->_expectation->getMock())
                ->setMethodName((string) $this->_expectation)
                ->setExpectedCountComparative('=')
                ->setExpectedCount($this->_limit)
                ->setActualCount($n);
            throw $exception;
        }
    }
}
CountValidator/AtLeast.php000066400000003504151520666110011557 0ustar00<?php
/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mockery/blob/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 *
 * @category   Mockery
 * @package    Mockery
 * @copyright  Copyright (c) 2010-2014 Pádraic Brady (http://blog.astrumfutura.com)
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
 */

namespace Mockery\CountValidator;

use Mockery;

class AtLeast extends CountValidatorAbstract
{

    /**
     * Checks if the validator can accept an additional nth call
     *
     * @param int $n
     * @return bool
     */
    public function isEligible($n)
    {
        return true;
    }

    /**
     * Validate the call count against this validator
     *
     * @param int $n
     * @return bool
     */
    public function validate($n)
    {
        if ($this->_limit > $n) {
            $exception = new Mockery\Exception\InvalidCountException(
                'Method ' . (string) $this->_expectation
                . ' from ' . $this->_expectation->getMock()->mockery_getName()
                . ' should be called' . PHP_EOL
                . ' at least ' . $this->_limit . ' times but called ' . $n
                . ' times.'
            );
            $exception->setMock($this->_expectation->getMock())
                ->setMethodName((string) $this->_expectation)
                ->setExpectedCountComparative('>=')
                ->setExpectedCount($this->_limit)
                ->setActualCount($n);
            throw $exception;
        }
    }
}
CountValidator/CountValidatorAbstract.php000066400000003237151520666110014647 0ustar00<?php
/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mockery/blob/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 *
 * @category   Mockery
 * @package    Mockery
 * @copyright  Copyright (c) 2010-2014 Pádraic Brady (http://blog.astrumfutura.com)
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
 */

namespace Mockery\CountValidator;

abstract class CountValidatorAbstract
{

    /**
     * Expectation for which this validator is assigned
     *
     * @var \Mockery\Expectation
     */
    protected $_expectation = null;

    /**
     * Call count limit
     *
     * @var int
     */
    protected $_limit = null;

    /**
     * Set Expectation object and upper call limit
     *
     * @param \Mockery\Expectation $expectation
     * @param int $limit
     */
    public function __construct(\Mockery\Expectation $expectation, $limit)
    {
        $this->_expectation = $expectation;
        $this->_limit = $limit;
    }

    /**
     * Checks if the validator can accept an additional nth call
     *
     * @param int $n
     * @return bool
     */
    public function isEligible($n)
    {
        return ($n < $this->_limit);
    }

    /**
     * Validate the call count against this validator
     *
     * @param int $n
     * @return bool
     */
    abstract public function validate($n);
}
CountValidator/Exception.php000066400000001405151520666110012156 0ustar00<?php
/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mockery/blob/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 *
 * @category   Mockery
 * @package    Mockery
 * @copyright  Copyright (c) 2010-2014 Pádraic Brady (http://blog.astrumfutura.com)
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
 */

namespace Mockery\CountValidator;

class Exception extends \OutOfBoundsException
{
}
CountValidator/AtMost.php000066400000003174151520666110011434 0ustar00<?php
/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mockery/blob/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 *
 * @category   Mockery
 * @package    Mockery
 * @copyright  Copyright (c) 2010-2014 Pádraic Brady (http://blog.astrumfutura.com)
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
 */

namespace Mockery\CountValidator;

use Mockery;

class AtMost extends CountValidatorAbstract
{

    /**
     * Validate the call count against this validator
     *
     * @param int $n
     * @return bool
     */
    public function validate($n)
    {
        if ($this->_limit < $n) {
            $exception = new Mockery\Exception\InvalidCountException(
                'Method ' . (string) $this->_expectation
                . ' from ' . $this->_expectation->getMock()->mockery_getName()
                . ' should be called' . PHP_EOL
                . ' at most ' . $this->_limit . ' times but called ' . $n
                . ' times.'
            );
            $exception->setMock($this->_expectation->getMock())
                ->setMethodName((string) $this->_expectation)
                ->setExpectedCountComparative('<=')
                ->setExpectedCount($this->_limit)
                ->setActualCount($n);
            throw $exception;
        }
    }
}
VerificationExpectation.php000066400000000432151520666110012107 0ustar00<?php

namespace Mockery;

class VerificationExpectation extends Expectation
{
    public function clearCountValidators()
    {
        $this->_countValidators = array();
    }

    public function __clone()
    {
        parent::__clone();
        $this->_actualCount = 0;
    }
}
Generator/StringManipulationGenerator.php000066400000001412151520666110014704 0ustar00<?php

namespace Mockery\Generator;

use Mockery\Generator\StringManipulation\Pass\Pass;

class StringManipulationGenerator implements Generator
{
    protected $passes = array();

    public function __construct(array $passes)
    {
        $this->passes = $passes;
    }

    public function generate(MockConfiguration $config)
    {
        $code = file_get_contents(__DIR__ . '/../Mock.php');
        $className = $config->getName() ?: $config->generateName();

        $namedConfig = $config->rename($className);

        foreach ($this->passes as $pass) {
            $code = $pass->apply($code, $namedConfig);
        }

        return new MockDefinition($namedConfig, $code);
    }

    public function addPass(Pass $pass)
    {
        $this->passes[] = $pass;
    }
}
Generator/MockConfiguration.php000066400000032177151520666110012643 0ustar00<?php

namespace Mockery\Generator;

/**
 * This class describes the configuration of mocks and hides away some of the
 * reflection implementation
 */
class MockConfiguration
{
    protected static $mockCounter = 0;

    /**
     * A class that we'd like to mock
     */
    protected $targetClass;
    protected $targetClassName;

    /**
     * A number of interfaces we'd like to mock, keyed by name to attempt to
     * keep unique
     */
    protected $targetInterfaces = array();
    protected $targetInterfaceNames = array();

    /**
     * An object we'd like our mock to proxy to
     */
    protected $targetObject;

    /**
     * The class name we'd like to use for a generated mock
     */
    protected $name;

    /**
     * Methods that should specifically not be mocked
     *
     * This is currently populated with stuff we don't know how to deal with,
     * should really be somewhere else
     */
    protected $blackListedMethods = array();

    /**
     * If not empty, only these methods will be mocked
     */
    protected $whiteListedMethods = array();

    /**
     * An instance mock is where we override the original class before it's
     * autoloaded
     */
    protected $instanceMock = false;

    /**
     * Param overrides
     */
    protected $parameterOverrides = array();

    /**
     * Instance cache of all methods
     */
    protected $allMethods;

    public function __construct(array $targets = array(), array $blackListedMethods = array(), array $whiteListedMethods = array(), $name = null, $instanceMock = false, array $parameterOverrides = array())
    {
        $this->addTargets($targets);
        $this->blackListedMethods = $blackListedMethods;
        $this->whiteListedMethods = $whiteListedMethods;
        $this->name = $name;
        $this->instanceMock = $instanceMock;
        $this->parameterOverrides = $parameterOverrides;
    }

    /**
     * Attempt to create a hash of the configuration, in order to allow caching
     *
     * @TODO workout if this will work
     *
     * @return string
     */
    public function getHash()
    {
        $vars = array(
            'targetClassName' => $this->targetClassName,
            'targetInterfaceNames' => $this->targetInterfaceNames,
            'name' => $this->name,
            'blackListedMethods' => $this->blackListedMethods,
            'whiteListedMethod' => $this->whiteListedMethods,
            'instanceMock' => $this->instanceMock,
            'parameterOverrides' => $this->parameterOverrides,
        );

        return md5(serialize($vars));
    }

    /**
     * Gets a list of methods from the classes, interfaces and objects and
     * filters them appropriately. Lot's of filtering going on, perhaps we could
     * have filter classes to iterate through
     */
    public function getMethodsToMock()
    {
        $methods = $this->getAllMethods();

        foreach ($methods as $key => $method) {
            if ($method->isFinal()) {
                unset($methods[$key]);
            }
        }

        /**
         * Whitelist trumps everything else
         */
        if (count($this->getWhiteListedMethods())) {
            $whitelist = array_map('strtolower', $this->getWhiteListedMethods());
            $methods = array_filter($methods, function ($method) use ($whitelist) {
                return $method->isAbstract() || in_array(strtolower($method->getName()), $whitelist);
            });

            return $methods;
        }

        /**
         * Remove blacklisted methods
         */
        if (count($this->getBlackListedMethods())) {
            $blacklist = array_map('strtolower', $this->getBlackListedMethods());
            $methods = array_filter($methods, function ($method) use ($blacklist) {
                return !in_array(strtolower($method->getName()), $blacklist);
            });
        }

        /**
         * Internal objects can not be instantiated with newInstanceArgs and if
         * they implement Serializable, unserialize will have to be called. As
         * such, we can't mock it and will need a pass to add a dummy
         * implementation
         */
        if ($this->getTargetClass()
            && $this->getTargetClass()->implementsInterface("Serializable")
            && $this->getTargetClass()->hasInternalAncestor()) {
            $methods = array_filter($methods, function ($method) {
                return $method->getName() !== "unserialize";
            });
        }

        return array_values($methods);
    }

    /**
     * We declare the __call method to handle undefined stuff, if the class
     * we're mocking has also defined it, we need to comply with their interface
     */
    public function requiresCallTypeHintRemoval()
    {
        foreach ($this->getAllMethods() as $method) {
            if ("__call" === $method->getName()) {
                $params = $method->getParameters();
                return !$params[1]->isArray();
            }
        }

        return false;
    }

    /**
     * We declare the __callStatic method to handle undefined stuff, if the class
     * we're mocking has also defined it, we need to comply with their interface
     */
    public function requiresCallStaticTypeHintRemoval()
    {
        foreach ($this->getAllMethods() as $method) {
            if ("__callStatic" === $method->getName()) {
                $params = $method->getParameters();
                return !$params[1]->isArray();
            }
        }

        return false;
    }

    public function rename($className)
    {
        $targets = array();

        if ($this->targetClassName) {
            $targets[] = $this->targetClassName;
        }

        if ($this->targetInterfaceNames) {
            $targets = array_merge($targets, $this->targetInterfaceNames);
        }

        if ($this->targetObject) {
            $targets[] = $this->targetObject;
        }

        return new self(
            $targets,
            $this->blackListedMethods,
            $this->whiteListedMethods,
            $className,
            $this->instanceMock,
            $this->parameterOverrides
        );
    }

    protected function addTarget($target)
    {
        if (is_object($target)) {
            $this->setTargetObject($target);
            $this->setTargetClassName(get_class($target));
            return $this;
        }

        if ($target[0] !== "\\") {
            $target = "\\" . $target;
        }

        if (class_exists($target)) {
            $this->setTargetClassName($target);
            return $this;
        }

        if (interface_exists($target)) {
            $this->addTargetInterfaceName($target);
            return $this;
        }

        /**
         * Default is to set as class, or interface if class already set
         *
         * Don't like this condition, can't remember what the default
         * targetClass is for
         */
        if ($this->getTargetClassName()) {
            $this->addTargetInterfaceName($target);
            return $this;
        }

        $this->setTargetClassName($target);
    }

    protected function addTargets($interfaces)
    {
        foreach ($interfaces as $interface) {
            $this->addTarget($interface);
        }
    }

    public function getTargetClassName()
    {
        return $this->targetClassName;
    }

    public function getTargetClass()
    {
        if ($this->targetClass) {
            return $this->targetClass;
        }

        if (!$this->targetClassName) {
            return null;
        }

        if (class_exists($this->targetClassName)) {
            $dtc = DefinedTargetClass::factory($this->targetClassName);

            if ($this->getTargetObject() == false && $dtc->isFinal()) {
                throw new \Mockery\Exception(
                    'The class ' . $this->targetClassName . ' is marked final and its methods'
                    . ' cannot be replaced. Classes marked final can be passed in'
                    . ' to \Mockery::mock() as instantiated objects to create a'
                    . ' partial mock, but only if the mock is not subject to type'
                    . ' hinting checks.'
                );
            }

            $this->targetClass = $dtc;
        } else {
            $this->targetClass = new UndefinedTargetClass($this->targetClassName);
        }

        return $this->targetClass;
    }

    public function getTargetInterfaces()
    {
        if (!empty($this->targetInterfaces)) {
            return $this->targetInterfaces;
        }

        foreach ($this->targetInterfaceNames as $targetInterface) {
            if (!interface_exists($targetInterface)) {
                $this->targetInterfaces[] = new UndefinedTargetClass($targetInterface);
                return;
            }

            $dtc = DefinedTargetClass::factory($targetInterface);
            $extendedInterfaces = array_keys($dtc->getInterfaces());
            $extendedInterfaces[] = $targetInterface;

            $traversableFound = false;
            $iteratorShiftedToFront = false;
            foreach ($extendedInterfaces as $interface) {
                if (!$traversableFound && preg_match("/^\\?Iterator(|Aggregate)$/i", $interface)) {
                    break;
                }

                if (preg_match("/^\\\\?IteratorAggregate$/i", $interface)) {
                    $this->targetInterfaces[] = DefinedTargetClass::factory("\\IteratorAggregate");
                    $iteratorShiftedToFront = true;
                } elseif (preg_match("/^\\\\?Iterator$/i", $interface)) {
                    $this->targetInterfaces[] = DefinedTargetClass::factory("\\Iterator");
                    $iteratorShiftedToFront = true;
                } elseif (preg_match("/^\\\\?Traversable$/i", $interface)) {
                    $traversableFound = true;
                }
            }

            if ($traversableFound && !$iteratorShiftedToFront) {
                $this->targetInterfaces[] = DefinedTargetClass::factory("\\IteratorAggregate");
            }

            /**
             * We never straight up implement Traversable
             */
            if (!preg_match("/^\\\\?Traversable$/i", $targetInterface)) {
                $this->targetInterfaces[] = $dtc;
            }
        }
        $this->targetInterfaces = array_unique($this->targetInterfaces); // just in case
        return $this->targetInterfaces;
    }

    public function getTargetObject()
    {
        return $this->targetObject;
    }

    public function getName()
    {
        return $this->name;
    }

    /**
     * Generate a suitable name based on the config
     */
    public function generateName()
    {
        $name = 'Mockery_' . static::$mockCounter++;

        if ($this->getTargetObject()) {
            $name .= "_" . str_replace("\\", "_", get_class($this->getTargetObject()));
        }

        if ($this->getTargetClass()) {
            $name .= "_" . str_replace("\\", "_", $this->getTargetClass()->getName());
        }

        if ($this->getTargetInterfaces()) {
            $name .= array_reduce($this->getTargetInterfaces(), function ($tmpname, $i) {
                $tmpname .= '_' . str_replace("\\", "_", $i->getName());
                return $tmpname;
            }, '');
        }

        return $name;
    }

    public function getShortName()
    {
        $parts = explode("\\", $this->getName());
        return array_pop($parts);
    }

    public function getNamespaceName()
    {
        $parts = explode("\\", $this->getName());
        array_pop($parts);

        if (count($parts)) {
            return implode("\\", $parts);
        }

        return "";
    }

    public function getBlackListedMethods()
    {
        return $this->blackListedMethods;
    }

    public function getWhiteListedMethods()
    {
        return $this->whiteListedMethods;
    }

    public function isInstanceMock()
    {
        return $this->instanceMock;
    }

    public function getParameterOverrides()
    {
        return $this->parameterOverrides;
    }

    protected function setTargetClassName($targetClassName)
    {
        $this->targetClassName = $targetClassName;
    }

    protected function getAllMethods()
    {
        if ($this->allMethods) {
            return $this->allMethods;
        }

        $classes = $this->getTargetInterfaces();

        if ($this->getTargetClass()) {
            $classes[] = $this->getTargetClass();
        }

        $methods = array();
        foreach ($classes as $class) {
            $methods = array_merge($methods, $class->getMethods());
        }

        $names = array();
        $methods = array_filter($methods, function ($method) use (&$names) {
            if (in_array($method->getName(), $names)) {
                return false;
            }

            $names[] = $method->getName();
            return true;
        });

        return $this->allMethods = $methods;
    }

    /**
     * If we attempt to implement Traversable, we must ensure we are also
     * implementing either Iterator or IteratorAggregate, and that whichever one
     * it is comes before Traversable in the list of implements.
     */
    protected function addTargetInterfaceName($targetInterface)
    {
        $this->targetInterfaceNames[] = $targetInterface;
    }


    protected function setTargetObject($object)
    {
        $this->targetObject = $object;
    }
}
Generator/MockConfigurationBuilder.php000066400000006323151520666110014144 0ustar00<?php

namespace Mockery\Generator;

class MockConfigurationBuilder
{
    protected $name;
    protected $blackListedMethods = array(
        '__call',
        '__callStatic',
        '__clone',
        '__wakeup',
        '__set',
        '__get',
        '__toString',
        '__isset',
        '__destruct',
        '__debugInfo',

        // below are reserved words in PHP
        "__halt_compiler", "abstract", "and", "array", "as",
        "break", "callable", "case", "catch", "class",
        "clone", "const", "continue", "declare", "default",
        "die", "do", "echo", "else", "elseif",
        "empty", "enddeclare", "endfor", "endforeach", "endif",
        "endswitch", "endwhile", "eval", "exit", "extends",
        "final", "for", "foreach", "function", "global",
        "goto", "if", "implements", "include", "include_once",
        "instanceof", "insteadof", "interface", "isset", "list",
        "namespace", "new", "or", "print", "private",
        "protected", "public", "require", "require_once", "return",
        "static", "switch", "throw", "trait", "try",
        "unset", "use", "var", "while", "xor"
    );
    protected $whiteListedMethods = array();
    protected $instanceMock = false;
    protected $parameterOverrides = array();

    protected $targets = array();

    public function addTarget($target)
    {
        $this->targets[] = $target;

        return $this;
    }

    public function addTargets($targets)
    {
        foreach ($targets as $target) {
            $this->addTarget($target);
        }

        return $this;
    }

    public function setName($name)
    {
        $this->name = $name;
        return $this;
    }

    public function addBlackListedMethod($blackListedMethod)
    {
        $this->blackListedMethods[] = $blackListedMethod;
        return $this;
    }

    public function addBlackListedMethods(array $blackListedMethods)
    {
        foreach ($blackListedMethods as $method) {
            $this->addBlackListedMethod($method);
        }
        return $this;
    }

    public function setBlackListedMethods(array $blackListedMethods)
    {
        $this->blackListedMethods = $blackListedMethods;
        return $this;
    }

    public function addWhiteListedMethod($whiteListedMethod)
    {
        $this->whiteListedMethods[] = $whiteListedMethod;
        return $this;
    }

    public function addWhiteListedMethods(array $whiteListedMethods)
    {
        foreach ($whiteListedMethods as $method) {
            $this->addWhiteListedMethod($method);
        }
        return $this;
    }

    public function setWhiteListedMethods(array $whiteListedMethods)
    {
        $this->whiteListedMethods = $whiteListedMethods;
        return $this;
    }

    public function setInstanceMock($instanceMock)
    {
        $this->instanceMock = (bool) $instanceMock;
    }

    public function setParameterOverrides(array $overrides)
    {
        $this->parameterOverrides = $overrides;
    }

    public function getMockConfiguration()
    {
        return new MockConfiguration(
            $this->targets,
            $this->blackListedMethods,
            $this->whiteListedMethods,
            $this->name,
            $this->instanceMock,
            $this->parameterOverrides
        );
    }
}
Generator/TargetClass.php000066400000001172151520666110011425 0ustar00<?php

namespace Mockery\Generator;

interface TargetClass
{
    /** @return string */
    public function getName();

    /** @return bool */
    public function isAbstract();

    /** @return bool */
    public function isFinal();

    /** @return Method[] */
    public function getMethods();

    /** @return string */
    public function getNamespaceName();

    /** @return bool */
    public function inNamespace();

    /** @return string */
    public function getShortName();

    /** @return bool */
    public function implementsInterface($interface);

    /** @return bool */
    public function hasInternalAncestor();
}
Generator/Generator.php000066400000000231151520666110011132 0ustar00<?php

namespace Mockery\Generator;

interface Generator
{
    /** @returns MockDefinition */
    public function generate(MockConfiguration $config);
}
Generator/DefinedTargetClass.php000066400000003355151520666110012711 0ustar00<?php

namespace Mockery\Generator;

class DefinedTargetClass
{
    private $rfc;

    public function __construct(\ReflectionClass $rfc)
    {
        $this->rfc = $rfc;
    }

    public static function factory($name)
    {
        return new self(new \ReflectionClass($name));
    }

    public function getName()
    {
        return $this->rfc->getName();
    }

    public function isAbstract()
    {
        return $this->rfc->isAbstract();
    }

    public function isFinal()
    {
        return $this->rfc->isFinal();
    }

    public function getMethods()
    {
        return array_map(function ($method) {
            return new Method($method);
        }, $this->rfc->getMethods());
    }

    public function getInterfaces()
    {
        $class = __CLASS__;
        return array_map(function ($interface) use ($class) {
            return new $class($interface);
        }, $this->rfc->getInterfaces());
    }

    public function __toString()
    {
        return $this->getName();
    }

    public function getNamespaceName()
    {
        return $this->rfc->getNamespaceName();
    }

    public function inNamespace()
    {
        return $this->rfc->inNamespace();
    }

    public function getShortName()
    {
        return $this->rfc->getShortName();
    }

    public function implementsInterface($interface)
    {
        return $this->rfc->implementsInterface($interface);
    }

    public function hasInternalAncestor()
    {
        if ($this->rfc->isInternal()) {
            return true;
        }

        $child = $this->rfc;
        while ($parent = $child->getParentClass()) {
            if ($parent->isInternal()) {
                return true;
            }
            $child = $parent;
        }

        return false;
    }
}
Generator/MockDefinition.php000066400000001151151520666110012110 0ustar00<?php

namespace Mockery\Generator;

class MockDefinition
{
    protected $config;
    protected $code;

    public function __construct(MockConfiguration $config, $code)
    {
        if (!$config->getName()) {
            throw new \InvalidArgumentException("MockConfiguration must contain a name");
        }
        $this->config = $config;
        $this->code = $code;
    }

    public function getConfig()
    {
        return $this->config;
    }

    public function getClassName()
    {
        return $this->config->getName();
    }

    public function getCode()
    {
        return $this->code;
    }
}
Generator/Parameter.php000066400000005146151520666110011136 0ustar00<?php

namespace Mockery\Generator;

class Parameter
{
    private static $parameterCounter;

    private $rfp;

    public function __construct(\ReflectionParameter $rfp)
    {
        $this->rfp = $rfp;
    }

    public function __call($method, array $args)
    {
        return call_user_func_array(array($this->rfp, $method), $args);
    }

    public function getClass()
    {
        return new DefinedTargetClass($this->rfp->getClass());
    }

    public function getTypeHintAsString()
    {
        if (method_exists($this->rfp, 'getTypehintText')) {
            // Available in HHVM
            $typehint = $this->rfp->getTypehintText();

            // not exhaustive, but will do for now
            if (in_array($typehint, array('int', 'integer', 'float', 'string', 'bool', 'boolean'))) {
                return '';
            }

            return $typehint;
        }

        if ($this->rfp->isArray()) {
            return 'array';
        }

        /*
         * PHP < 5.4.1 has some strange behaviour with a typehint of self and
         * subclass signatures, so we risk the regexp instead
         */
        if ((version_compare(PHP_VERSION, '5.4.1') >= 0)) {
            try {
                if ($this->rfp->getClass()) {
                    return $this->getOptionalSign() . $this->rfp->getClass()->getName();
                }
            } catch (\ReflectionException $re) {
                // noop
            }
        }

        if (version_compare(PHP_VERSION, '7.0.0-dev') >= 0 && $this->rfp->hasType()) {
            return $this->getOptionalSign() . $this->rfp->getType();
        }

        if (preg_match('/^Parameter #[0-9]+ \[ \<(required|optional)\> (?<typehint>\S+ )?.*\$' . $this->rfp->getName() . ' .*\]$/', $this->rfp->__toString(), $typehintMatch)) {
            if (!empty($typehintMatch['typehint'])) {
                return $typehintMatch['typehint'];
            }
        }

        return '';
    }

    private function getOptionalSign()
    {
        if (version_compare(PHP_VERSION, '7.1.0-dev', '>=') && $this->rfp->allowsNull() && !$this->rfp->isVariadic()) {
            return '?';
        }

        return '';
    }

    /**
     * Some internal classes have funny looking definitions...
     */
    public function getName()
    {
        $name = $this->rfp->getName();
        if (!$name || $name == '...') {
            $name = 'arg' . static::$parameterCounter++;
        }

        return $name;
    }


    /**
     * Variadics only introduced in 5.6
     */
    public function isVariadic()
    {
        return version_compare(PHP_VERSION, '5.6.0') >= 0 && $this->rfp->isVariadic();
    }
}
Generator/StringManipulation/Pass/ClassNamePass.php000066400000001222151520666110016437 0ustar00<?php

namespace Mockery\Generator\StringManipulation\Pass;

use Mockery\Generator\MockConfiguration;

class ClassNamePass implements Pass
{
    public function apply($code, MockConfiguration $config)
    {
        $namespace = $config->getNamespaceName();

        $namespace = ltrim($namespace, "\\");

        $className = $config->getShortName();

        $code = str_replace(
            'namespace Mockery;',
            $namespace ? 'namespace ' . $namespace . ';' : '',
            $code
        );

        $code = str_replace(
            'class Mock',
            'class ' . $className,
            $code
        );

        return $code;
    }
}
Generator/StringManipulation/Pass/RemoveUnserializeForInternalSerializableClassesPass.php000066400000002140151520666110026252 0ustar00<?php

namespace Mockery\Generator\StringManipulation\Pass;

use Mockery\Generator\MockConfiguration;

/**
 * Internal classes can not be instantiated with the newInstanceWithoutArgs
 * reflection method, so need the serialization hack. If the class also
 * implements Serializable, we need to replace the standard unserialize method
 * definition with a dummy
 */
class RemoveUnserializeForInternalSerializableClassesPass
{
    const DUMMY_METHOD_DEFINITION = 'public function unserialize($string) {} ';

    public function apply($code, MockConfiguration $config)
    {
        $target = $config->getTargetClass();

        if (!$target) {
            return $code;
        }

        if (!$target->hasInternalAncestor() || !$target->implementsInterface("Serializable")) {
            return $code;
        }

        $code = $this->appendToClass($code, self::DUMMY_METHOD_DEFINITION);

        return $code;
    }

    protected function appendToClass($class, $code)
    {
        $lastBrace = strrpos($class, "}");
        $class = substr($class, 0, $lastBrace) . $code . "\n    }\n";
        return $class;
    }
}
Generator/StringManipulation/Pass/Pass.php000066400000000267151520666110014660 0ustar00<?php

namespace Mockery\Generator\StringManipulation\Pass;

use Mockery\Generator\MockConfiguration;

interface Pass
{
    public function apply($code, MockConfiguration $config);
}
Generator/StringManipulation/Pass/CallTypeHintPass.php000066400000001422151520666110017133 0ustar00<?php

namespace Mockery\Generator\StringManipulation\Pass;

use Mockery\Generator\MockConfiguration;

class CallTypeHintPass implements Pass
{
    public function apply($code, MockConfiguration $config)
    {
        if ($config->requiresCallTypeHintRemoval()) {
            $code = str_replace(
                'public function __call($method, array $args)',
                'public function __call($method, $args)',
                $code
            );
        }

        if ($config->requiresCallStaticTypeHintRemoval()) {
            $code = str_replace(
                'public static function __callStatic($method, array $args)',
                'public static function __callStatic($method, $args)',
                $code
            );
        }

        return $code;
    }
}
Generator/StringManipulation/Pass/RemoveBuiltinMethodsThatAreFinalPass.php000066400000001676151520666110023141 0ustar00<?php

namespace Mockery\Generator\StringManipulation\Pass;

use Mockery\Generator\MockConfiguration;

/**
 * The standard Mockery\Mock class includes some methods to ease mocking, such
 * as __wakeup, however if the target has a final __wakeup method, it can't be
 * mocked. This pass removes the builtin methods where they are final on the
 * target
 */
class RemoveBuiltinMethodsThatAreFinalPass
{
    protected $methods = array(
        '__wakeup' => '/public function __wakeup\(\)\s+\{.*?\}/sm',
    );

    public function apply($code, MockConfiguration $config)
    {
        $target = $config->getTargetClass();

        if (!$target) {
            return $code;
        }

        foreach ($target->getMethods() as $method) {
            if ($method->isFinal() && isset($this->methods[$method->getName()])) {
                $code = preg_replace($this->methods[$method->getName()], '', $code);
            }
        }

        return $code;
    }
}
Generator/StringManipulation/Pass/ClassPass.php000066400000002477151520666110015653 0ustar00<?php

namespace Mockery\Generator\StringManipulation\Pass;

use Mockery\Generator\MockConfiguration;

class ClassPass implements Pass
{
    public function apply($code, MockConfiguration $config)
    {
        $target = $config->getTargetClass();

        if (!$target) {
            return $code;
        }

        if ($target->isFinal()) {
            return $code;
        }

        $className = ltrim($target->getName(), "\\");
        if (!class_exists($className)) {
            $targetCode = '<?php ';

            if ($target->inNamespace()) {
                $targetCode.= 'namespace ' . $target->getNamespaceName(). '; ';
            }

            $targetCode.= 'class ' . $target->getShortName() . ' {} ';

            /*
             * We could eval here, but it doesn't play well with the way
             * PHPUnit tries to backup global state and the require definition
             * loader
             */
            $tmpfname = tempnam(sys_get_temp_dir(), "Mockery");
            file_put_contents($tmpfname, $targetCode);
            require $tmpfname;
            \Mockery::registerFileForCleanUp($tmpfname);
        }

        $code = str_replace(
            "implements MockInterface",
            "extends \\" . $className . " implements MockInterface",
            $code
        );

        return $code;
    }
}
Generator/StringManipulation/Pass/InterfacePass.php000066400000001054151520666110016474 0ustar00<?php

namespace Mockery\Generator\StringManipulation\Pass;

use Mockery\Generator\MockConfiguration;

class InterfacePass implements Pass
{
    public function apply($code, MockConfiguration $config)
    {
        $interfaces = array_reduce((array) $config->getTargetInterfaces(), function ($code, $i) {
            return $code . ", \\" . $i->getName();
        }, "");

        $code = str_replace(
            "implements MockInterface",
            "implements MockInterface" . $interfaces,
            $code
        );

        return $code;
    }
}
Generator/StringManipulation/Pass/InstanceMockPass.php000066400000003524151520666110017156 0ustar00<?php

namespace Mockery\Generator\StringManipulation\Pass;

use Mockery\Generator\MockConfiguration;

class InstanceMockPass
{
    const INSTANCE_MOCK_CODE = <<<MOCK

    protected \$_mockery_ignoreVerification = true;

    public function __construct()
    {
        \$this->_mockery_ignoreVerification = false;
        \$associatedRealObject = \Mockery::fetchMock(__CLASS__);

        foreach (get_object_vars(\$this) as \$attr => \$val) {
            if (\$attr !== "_mockery_ignoreVerification" && \$attr !== "_mockery_expectations") {
                \$this->\$attr = \$associatedRealObject->\$attr;
            }
        }

        \$directors = \$associatedRealObject->mockery_getExpectations();
        foreach (\$directors as \$method=>\$director) {
            \$expectations = \$director->getExpectations();
            // get the director method needed
            \$existingDirector = \$this->mockery_getExpectationsFor(\$method);
            if (!\$existingDirector) {
                \$existingDirector = new \Mockery\ExpectationDirector(\$method, \$this);
                \$this->mockery_setExpectationsFor(\$method, \$existingDirector);
            }
            foreach (\$expectations as \$expectation) {
                \$clonedExpectation = clone \$expectation;
                \$existingDirector->addExpectation(\$clonedExpectation);
            }
        }
        \Mockery::getContainer()->rememberMock(\$this);
    }
MOCK;

    public function apply($code, MockConfiguration $config)
    {
        if ($config->isInstanceMock()) {
            $code = $this->appendToClass($code, static::INSTANCE_MOCK_CODE);
        }

        return $code;
    }

    protected function appendToClass($class, $code)
    {
        $lastBrace = strrpos($class, "}");
        $class = substr($class, 0, $lastBrace) . $code . "\n    }\n";
        return $class;
    }
}
Generator/StringManipulation/Pass/MethodDefinitionPass.php000066400000011346151520666110020032 0ustar00<?php

namespace Mockery\Generator\StringManipulation\Pass;

use Mockery\Generator\Method;
use Mockery\Generator\MockConfiguration;

class MethodDefinitionPass implements Pass
{
    public function apply($code, MockConfiguration $config)
    {
        foreach ($config->getMethodsToMock() as $method) {
            if ($method->isPublic()) {
                $methodDef = 'public';
            } elseif ($method->isProtected()) {
                $methodDef = 'protected';
            } else {
                $methodDef = 'private';
            }

            if ($method->isStatic()) {
                $methodDef .= ' static';
            }

            $methodDef .= ' function ';
            $methodDef .= $method->returnsReference() ? ' & ' : '';
            $methodDef .= $method->getName();
            $methodDef .= $this->renderParams($method, $config);
            $methodDef .= $this->renderReturnType($method);
            $methodDef .= $this->renderMethodBody($method, $config);

            $code = $this->appendToClass($code, $methodDef);
        }

        return $code;
    }

    protected function renderParams(Method $method, $config)
    {
        $class = $method->getDeclaringClass();
        if ($class->isInternal()) {
            $overrides = $config->getParameterOverrides();

            if (isset($overrides[strtolower($class->getName())][$method->getName()])) {
                return '(' . implode(',', $overrides[strtolower($class->getName())][$method->getName()]) . ')';
            }
        }

        $methodParams = array();
        $params = $method->getParameters();
        foreach ($params as $param) {
            $paramDef = $param->getTypeHintAsString();
            $paramDef .= $param->isPassedByReference() ? '&' : '';
            $paramDef .= $param->isVariadic() ? '...' : '';
            $paramDef .= '$' . $param->getName();

            if (!$param->isVariadic()) {
                if (false !== $param->isDefaultValueAvailable()) {
                    $paramDef .= ' = ' . var_export($param->getDefaultValue(), true);
                } elseif ($param->isOptional()) {
                    $paramDef .= ' = null';
                }
            }

            $methodParams[] = $paramDef;
        }
        return '(' . implode(', ', $methodParams) . ')';
    }

    protected function renderReturnType(Method $method)
    {
        $type = $method->getReturnType();
        return $type ? sprintf(': %s', $type) : '';
    }

    protected function appendToClass($class, $code)
    {
        $lastBrace = strrpos($class, "}");
        $class = substr($class, 0, $lastBrace) . $code . "\n    }\n";
        return $class;
    }

    private function renderMethodBody($method, $config)
    {
        /** @var \ReflectionMethod $method */
        $invoke = $method->isStatic() ? 'static::_mockery_handleStaticMethodCall' : '$this->_mockery_handleMethodCall';
        $body = <<<BODY
{
\$argc = func_num_args();
\$argv = func_get_args();

BODY;

        // Fix up known parameters by reference - used func_get_args() above
        // in case more parameters are passed in than the function definition
        // says - eg varargs.
        $class = $method->getDeclaringClass();
        $class_name = strtolower($class->getName());
        $overrides = $config->getParameterOverrides();
        if (isset($overrides[$class_name][$method->getName()])) {
            $params = array_values($overrides[$class_name][$method->getName()]);
            $paramCount = count($params);
            for ($i = 0; $i < $paramCount; ++$i) {
                $param = $params[$i];
                if (strpos($param, '&') !== false) {
                    if (($stripDefaultValue = strpos($param, '=')) !== false) {
                        $param = trim(substr($param, 0, $stripDefaultValue));
                    }
                    $body .= <<<BODY
if (\$argc > $i) {
    \$argv[$i] = {$param};
}

BODY;
                }
            }
        } else {
            /** @var \ReflectionParameter[] $params */
            $params = array_values($method->getParameters());
            $paramCount = count($params);
            for ($i = 0; $i < $paramCount; ++$i) {
                $param = $params[$i];
                if (!$param->isPassedByReference()) {
                    continue;
                }
                $body .= <<<BODY
if (\$argc > $i) {
    \$argv[$i] =& \${$param->getName()};
}

BODY;
            }
        }

        $body .= $this->getReturnStatement($method, $invoke);

        return $body;
    }

    private function getReturnStatement($method, $invoke)
    {
        if ($method->getReturnType() === 'void') {
            return <<<BODY
{$invoke}(__FUNCTION__, \$argv);
}
BODY;
        }

        return <<<BODY
\$ret = {$invoke}(__FUNCTION__, \$argv);
return \$ret;
}
BODY;
    }
}
Generator/Method.php000066400000002100151520666110010421 0ustar00<?php

namespace Mockery\Generator;

class Method
{
    private $method;

    public function __construct(\ReflectionMethod $method)
    {
        $this->method = $method;
    }

    public function __call($method, $args)
    {
        return call_user_func_array(array($this->method, $method), $args);
    }

    public function getParameters()
    {
        return array_map(function ($parameter) {
            return new Parameter($parameter);
        }, $this->method->getParameters());
    }

    public function getReturnType()
    {
        if (version_compare(PHP_VERSION, '7.0.0-dev') >= 0 && $this->method->hasReturnType()) {
            $returnType = (string) $this->method->getReturnType();

            if ('self' === $returnType) {
                $returnType = "\\".$this->method->getDeclaringClass()->getName();
            }

            if (version_compare(PHP_VERSION, '7.1.0-dev') >= 0 && $this->method->getReturnType()->allowsNull()) {
                $returnType = '?'.$returnType;
            }

            return $returnType;
        }
        return '';
    }
}
Generator/CachingGenerator.php000066400000001102151520666110012405 0ustar00<?php

namespace Mockery\Generator;

class CachingGenerator implements Generator
{
    protected $generator;
    protected $cache = array();

    public function __construct(Generator $generator)
    {
        $this->generator = $generator;
    }

    public function generate(MockConfiguration $config)
    {
        $hash = $config->getHash();
        if (isset($this->cache[$hash])) {
            return $this->cache[$hash];
        }

        $definition = $this->generator->generate($config);
        $this->cache[$hash] = $definition;

        return $definition;
    }
}
Generator/UndefinedTargetClass.php000066400000001766151520666110013260 0ustar00<?php

namespace Mockery\Generator;

class UndefinedTargetClass
{
    private $name;

    public function __construct($name)
    {
        $this->name = $name;
    }

    public function getName()
    {
        return $this->name;
    }

    public function isAbstract()
    {
        return false;
    }

    public function isFinal()
    {
        return false;
    }

    public function getMethods()
    {
        return array();
    }

    public function getNamespaceName()
    {
        $parts = explode("\\", ltrim($this->getName(), "\\"));
        array_pop($parts);
        return implode("\\", $parts);
    }

    public function inNamespace()
    {
        return $this->getNamespaceName() !== '';
    }

    public function getShortName()
    {
        $parts = explode("\\", $this->getName());
        return array_pop($parts);
    }

    public function implementsInterface($interface)
    {
        return false;
    }

    public function hasInternalAncestor()
    {
        return false;
    }
}
Mock.php000066400000053066151520666110006165 0ustar00<?php
/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mockery/blob/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 *
 * @category   Mockery
 * @package    Mockery
 * @copyright  Copyright (c) 2010-2014 Pádraic Brady (http://blog.astrumfutura.com)
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
 */

namespace Mockery;

use Mockery\MockInterface;

class Mock implements MockInterface
{

    /**
     * Stores an array of all expectation directors for this mock
     *
     * @var array
     */
    protected $_mockery_expectations = array();

    /**
     * Flag to indicate whether we can ignore method calls missing from our
     * expectations
     *
     * @var bool
     */
    protected $_mockery_ignoreMissing = false;

    /**
     * Flag to indicate whether we can defer method calls missing from our
     * expectations
     *
     * @var bool
     */
    protected $_mockery_deferMissing = false;

    /**
     * Flag to indicate whether this mock was verified
     *
     * @var bool
     */
    protected $_mockery_verified = false;

    /**
     * Given name of the mock
     *
     * @var string
     */
    protected $_mockery_name = null;

    /**
     * Order number of allocation
     *
     * @var int
     */
    protected $_mockery_allocatedOrder = 0;

    /**
     * Current ordered number
     *
     * @var int
     */
    protected $_mockery_currentOrder = 0;

    /**
     * Ordered groups
     *
     * @var array
     */
    protected $_mockery_groups = array();

    /**
     * Mock container containing this mock object
     *
     * @var \Mockery\Container
     */
    protected $_mockery_container = null;

    /**
     * Instance of a core object on which methods are called in the event
     * it has been set, and an expectation for one of the object's methods
     * does not exist. This implements a simple partial mock proxy system.
     *
     * @var object
     */
    protected $_mockery_partial = null;

    /**
     * Flag to indicate we should ignore all expectations temporarily. Used
     * mainly to prevent expectation matching when in the middle of a mock
     * object recording session.
     *
     * @var bool
     */
    protected $_mockery_disableExpectationMatching = false;

    /**
     * Stores all stubbed public methods separate from any on-object public
     * properties that may exist.
     *
     * @var array
     */
    protected $_mockery_mockableProperties = array();

    /**
     * @var array
     */
    protected $_mockery_mockableMethods = array();

    /**
     * Just a local cache for this mock's target's methods
     *
     * @var ReflectionMethod[]
     */
    protected static $_mockery_methods;

    protected $_mockery_allowMockingProtectedMethods = false;

    protected $_mockery_receivedMethodCalls;

    /**
     * If shouldIgnoreMissing is called, this value will be returned on all calls to missing methods
     * @var mixed
     */
    protected $_mockery_defaultReturnValue = null;

    /**
     * We want to avoid constructors since class is copied to Generator.php
     * for inclusion on extending class definitions.
     *
     * @param \Mockery\Container $container
     * @param object $partialObject
     * @return void
     */
    public function mockery_init(\Mockery\Container $container = null, $partialObject = null)
    {
        if (is_null($container)) {
            $container = new \Mockery\Container;
        }
        $this->_mockery_container = $container;
        if (!is_null($partialObject)) {
            $this->_mockery_partial = $partialObject;
        }

        if (!\Mockery::getConfiguration()->mockingNonExistentMethodsAllowed()) {
            foreach ($this->mockery_getMethods() as $method) {
                if ($method->isPublic() && !$method->isStatic()) {
                    $this->_mockery_mockableMethods[] = $method->getName();
                }
            }
        }
    }

    /**
     * Set expected method calls
     *
     * @param mixed
     * @return \Mockery\Expectation
     */
    public function shouldReceive()
    {
        /** @var array $nonPublicMethods */
        $nonPublicMethods = $this->getNonPublicMethods();

        $self = $this;
        $allowMockingProtectedMethods = $this->_mockery_allowMockingProtectedMethods;

        $lastExpectation = \Mockery::parseShouldReturnArgs(
            $this, func_get_args(), function ($method) use ($self, $nonPublicMethods, $allowMockingProtectedMethods) {
                $rm = $self->mockery_getMethod($method);
                if ($rm) {
                    if ($rm->isPrivate()) {
                        throw new \InvalidArgumentException("$method() cannot be mocked as it is a private method");
                    }
                    if (!$allowMockingProtectedMethods && $rm->isProtected()) {
                        throw new \InvalidArgumentException("$method() cannot be mocked as it a protected method and mocking protected methods is not allowed for this mock");
                    }
                }

                $director = $self->mockery_getExpectationsFor($method);
                if (!$director) {
                    $director = new \Mockery\ExpectationDirector($method, $self);
                    $self->mockery_setExpectationsFor($method, $director);
                }
                $expectation = new \Mockery\Expectation($self, $method);
                $director->addExpectation($expectation);
                return $expectation;
            }
        );
        return $lastExpectation;
    }

    /**
     * Shortcut method for setting an expectation that a method should not be called.
     *
     * @param mixed
     * @return \Mockery\Expectation
     */
    public function shouldNotReceive()
    {
        $expectation = call_user_func_array(array($this, 'shouldReceive'), func_get_args());
        $expectation->never();
        return $expectation;
    }

    /**
     * Allows additional methods to be mocked that do not explicitly exist on mocked class
     * @param String $method name of the method to be mocked
     * @return Mock
     */
    public function shouldAllowMockingMethod($method)
    {
        $this->_mockery_mockableMethods[] = $method;
        return $this;
    }

    /**
     * Set mock to ignore unexpected methods and return Undefined class
     * @param mixed $returnValue the default return value for calls to missing functions on this mock
     * @return Mock
     */
    public function shouldIgnoreMissing($returnValue = null)
    {
        $this->_mockery_ignoreMissing = true;
        $this->_mockery_defaultReturnValue = $returnValue;
        return $this;
    }

    public function asUndefined()
    {
        $this->_mockery_ignoreMissing = true;
        $this->_mockery_defaultReturnValue = new \Mockery\Undefined;
        return $this;
    }

    /**
     * @return Mock
     */
    public function shouldAllowMockingProtectedMethods()
    {
        $this->_mockery_allowMockingProtectedMethods = true;
        return $this;
    }


    /**
     * Set mock to defer unexpected methods to it's parent
     *
     * This is particularly useless for this class, as it doesn't have a parent,
     * but included for completeness
     *
     * @return Mock
     */
    public function shouldDeferMissing()
    {
        $this->_mockery_deferMissing = true;
        return $this;
    }

    /**
     * Create an obviously worded alias to shouldDeferMissing()
     *
     * @return Mock
     */
    public function makePartial()
    {
        return $this->shouldDeferMissing();
    }

    /**
     * Accepts a closure which is executed with an object recorder which proxies
     * to the partial source object. The intent being to record the
     * interactions of a concrete object as a set of expectations on the
     * current mock object. The partial may then be passed to a second process
     * to see if it fulfils the same (or exact same) contract as the original.
     *
     * @param Closure $closure
     */
    public function shouldExpect(\Closure $closure)
    {
        $recorder = new \Mockery\Recorder($this, $this->_mockery_partial);
        $this->_mockery_disableExpectationMatching = true;
        $closure($recorder);
        $this->_mockery_disableExpectationMatching = false;
        return $this;
    }

    /**
     * In the event shouldReceive() accepting one or more methods/returns,
     * this method will switch them from normal expectations to default
     * expectations
     *
     * @return self
     */
    public function byDefault()
    {
        foreach ($this->_mockery_expectations as $director) {
            $exps = $director->getExpectations();
            foreach ($exps as $exp) {
                $exp->byDefault();
            }
        }
        return $this;
    }

    /**
     * Capture calls to this mock
     */
    public function __call($method, array $args)
    {
        return $this->_mockery_handleMethodCall($method, $args);
    }

    public static function __callStatic($method, array $args)
    {
        return self::_mockery_handleStaticMethodCall($method, $args);
    }

    /**
     * Forward calls to this magic method to the __call method
     */
    public function __toString()
    {
        return $this->__call('__toString', array());
    }

    /**public function __set($name, $value)
    {
        $this->_mockery_mockableProperties[$name] = $value;
        return $this;
    }

    public function __get($name)
    {
        if (isset($this->_mockery_mockableProperties[$name])) {
            return $this->_mockery_mockableProperties[$name];
        } elseif(isset($this->{$name})) {
            return $this->{$name};
        }
        throw new \InvalidArgumentException (
            'Property ' . __CLASS__ . '::' . $name . ' does not exist on this mock object'
        );
    }**/

    /**
     * Iterate across all expectation directors and validate each
     *
     * @throws \Mockery\CountValidator\Exception
     * @return void
     */
    public function mockery_verify()
    {
        if ($this->_mockery_verified) {
            return true;
        }
        if (isset($this->_mockery_ignoreVerification)
            && $this->_mockery_ignoreVerification == true) {
            return true;
        }
        $this->_mockery_verified = true;
        foreach ($this->_mockery_expectations as $director) {
            $director->verify();
        }
    }

    /**
     * Tear down tasks for this mock
     *
     * @return void
     */
    public function mockery_teardown()
    {
    }

    /**
     * Fetch the next available allocation order number
     *
     * @return int
     */
    public function mockery_allocateOrder()
    {
        $this->_mockery_allocatedOrder += 1;
        return $this->_mockery_allocatedOrder;
    }

    /**
     * Set ordering for a group
     *
     * @param mixed $group
     * @param int $order
     */
    public function mockery_setGroup($group, $order)
    {
        $this->_mockery_groups[$group] = $order;
    }

    /**
     * Fetch array of ordered groups
     *
     * @return array
     */
    public function mockery_getGroups()
    {
        return $this->_mockery_groups;
    }

    /**
     * Set current ordered number
     *
     * @param int $order
     */
    public function mockery_setCurrentOrder($order)
    {
        $this->_mockery_currentOrder = $order;
        return $this->_mockery_currentOrder;
    }

    /**
     * Get current ordered number
     *
     * @return int
     */
    public function mockery_getCurrentOrder()
    {
        return $this->_mockery_currentOrder;
    }

    /**
     * Validate the current mock's ordering
     *
     * @param string $method
     * @param int $order
     * @throws \Mockery\Exception
     * @return void
     */
    public function mockery_validateOrder($method, $order)
    {
        if ($order < $this->_mockery_currentOrder) {
            $exception = new \Mockery\Exception\InvalidOrderException(
                'Method ' . __CLASS__ . '::' . $method . '()'
                . ' called out of order: expected order '
                . $order . ', was ' . $this->_mockery_currentOrder
            );
            $exception->setMock($this)
                ->setMethodName($method)
                ->setExpectedOrder($order)
                ->setActualOrder($this->_mockery_currentOrder);
            throw $exception;
        }
        $this->mockery_setCurrentOrder($order);
    }

    /**
     * Gets the count of expectations for this mock
     *
     * @return int
     */
    public function mockery_getExpectationCount()
    {
        $count = 0;
        foreach ($this->_mockery_expectations as $director) {
            $count += $director->getExpectationCount();
        }
        return $count;
    }

    /**
     * Return the expectations director for the given method
     *
     * @var string $method
     * @return \Mockery\ExpectationDirector|null
     */
    public function mockery_setExpectationsFor($method, \Mockery\ExpectationDirector $director)
    {
        $this->_mockery_expectations[$method] = $director;
    }

    /**
     * Return the expectations director for the given method
     *
     * @var string $method
     * @return \Mockery\ExpectationDirector|null
     */
    public function mockery_getExpectationsFor($method)
    {
        if (isset($this->_mockery_expectations[$method])) {
            return $this->_mockery_expectations[$method];
        }
    }

    /**
     * Find an expectation matching the given method and arguments
     *
     * @var string $method
     * @var array $args
     * @return \Mockery\Expectation|null
     */
    public function mockery_findExpectation($method, array $args)
    {
        if (!isset($this->_mockery_expectations[$method])) {
            return null;
        }
        $director = $this->_mockery_expectations[$method];

        return $director->findExpectation($args);
    }

    /**
     * Return the container for this mock
     *
     * @return \Mockery\Container
     */
    public function mockery_getContainer()
    {
        return $this->_mockery_container;
    }

    /**
     * Return the name for this mock
     *
     * @return string
     */
    public function mockery_getName()
    {
        return __CLASS__;
    }

    /**
     * @return array
     */
    public function mockery_getMockableProperties()
    {
        return $this->_mockery_mockableProperties;
    }

    public function __isset($name)
    {
        if (false === stripos($name, '_mockery_') && method_exists(get_parent_class($this), '__isset')) {
            return parent::__isset($name);
        }
    }

    public function mockery_getExpectations()
    {
        return $this->_mockery_expectations;
    }

    /**
     * Calls a parent class method and returns the result. Used in a passthru
     * expectation where a real return value is required while still taking
     * advantage of expectation matching and call count verification.
     *
     * @param string $name
     * @param array $args
     * @return mixed
     */
    public function mockery_callSubjectMethod($name, array $args)
    {
        return call_user_func_array('parent::' . $name, $args);
    }

    /**
     * @return string[]
     */
    public function mockery_getMockableMethods()
    {
        return $this->_mockery_mockableMethods;
    }

    /**
     * @return bool
     */
    public function mockery_isAnonymous()
    {
        $rfc = new \ReflectionClass($this);
        return false === $rfc->getParentClass();
    }

    public function __wakeup()
    {
        /**
         * This does not add __wakeup method support. It's a blind method and any
         * expected __wakeup work will NOT be performed. It merely cuts off
         * annoying errors where a __wakeup exists but is not essential when
         * mocking
         */
    }

    public function mockery_getMethod($name)
    {
        foreach ($this->mockery_getMethods() as $method) {
            if ($method->getName() == $name) {
                return $method;
            }
        }

        return null;
    }

    public function shouldHaveReceived($method, $args = null)
    {
        $expectation = new \Mockery\VerificationExpectation($this, $method);
        if (null !== $args) {
            $expectation->withArgs($args);
        }
        $expectation->atLeast()->once();
        $director = new \Mockery\VerificationDirector($this->_mockery_getReceivedMethodCalls(), $expectation);
        $director->verify();
        return $director;
    }

    public function shouldNotHaveReceived($method, $args = null)
    {
        $expectation = new \Mockery\VerificationExpectation($this, $method);
        if (null !== $args) {
            $expectation->withArgs($args);
        }
        $expectation->never();
        $director = new \Mockery\VerificationDirector($this->_mockery_getReceivedMethodCalls(), $expectation);
        $director->verify();
        return null;
    }

    protected static function _mockery_handleStaticMethodCall($method, array $args)
    {
        try {
            $associatedRealObject = \Mockery::fetchMock(__CLASS__);
            return $associatedRealObject->__call($method, $args);
        } catch (\BadMethodCallException $e) {
            throw new \BadMethodCallException(
                'Static method ' . $associatedRealObject->mockery_getName() . '::' . $method
                . '() does not exist on this mock object'
            );
        }
    }

    protected function _mockery_getReceivedMethodCalls()
    {
        return $this->_mockery_receivedMethodCalls ?: $this->_mockery_receivedMethodCalls = new \Mockery\ReceivedMethodCalls();
    }

    protected function _mockery_handleMethodCall($method, array $args)
    {
        $this->_mockery_getReceivedMethodCalls()->push(new \Mockery\MethodCall($method, $args));

        $rm = $this->mockery_getMethod($method);
        if ($rm && $rm->isProtected() && !$this->_mockery_allowMockingProtectedMethods) {
            if ($rm->isAbstract()) {
                return;
            }

            try {
                $prototype = $rm->getPrototype();
                if ($prototype->isAbstract()) {
                    return;
                }
            } catch (\ReflectionException $re) {
                // noop - there is no hasPrototype method
            }

            return call_user_func_array("parent::$method", $args);
        }

        if (isset($this->_mockery_expectations[$method])
        && !$this->_mockery_disableExpectationMatching) {
            $handler = $this->_mockery_expectations[$method];

            try {
                return $handler->call($args);
            } catch (\Mockery\Exception\NoMatchingExpectationException $e) {
                if (!$this->_mockery_ignoreMissing && !$this->_mockery_deferMissing) {
                    throw $e;
                }
            }
        }

        if (!is_null($this->_mockery_partial) && method_exists($this->_mockery_partial, $method)) {
            return call_user_func_array(array($this->_mockery_partial, $method), $args);
        } elseif ($this->_mockery_deferMissing && is_callable("parent::$method")) {
            return call_user_func_array("parent::$method", $args);
        } elseif ($method === '__toString') {
            // __toString is special because we force its addition to the class API regardless of the
            // original implementation.  Thus, we should always return a string rather than honor
            // _mockery_ignoreMissing and break the API with an error.
            return sprintf("%s#%s", __CLASS__, spl_object_hash($this));
        } elseif ($this->_mockery_ignoreMissing) {
            if (\Mockery::getConfiguration()->mockingNonExistentMethodsAllowed() || (method_exists($this->_mockery_partial, $method) || is_callable("parent::$method"))) {
                if ($this->_mockery_defaultReturnValue instanceof \Mockery\Undefined) {
                    return call_user_func_array(array($this->_mockery_defaultReturnValue, $method), $args);
                } else {
                    return $this->_mockery_defaultReturnValue;
                }
            }
        }
        throw new \BadMethodCallException(
            'Method ' . __CLASS__ . '::' . $method . '() does not exist on this mock object'
        );
    }

    protected function mockery_getMethods()
    {
        if (static::$_mockery_methods) {
            return static::$_mockery_methods;
        }

        $methods = array();

        if (isset($this->_mockery_partial)) {
            $reflected = new \ReflectionObject($this->_mockery_partial);
            $methods = $reflected->getMethods();
        } else {
            $reflected = new \ReflectionClass($this);
            foreach ($reflected->getMethods() as $method) {
                try {
                    $methods[] = $method->getPrototype();
                } catch (\ReflectionException $re) {
                    /**
                     * For some reason, private methods don't have a prototype
                     */
                    if ($method->isPrivate()) {
                        $methods[] = $method;
                    }
                }
            }
        }

        return static::$_mockery_methods = $methods;
    }

    /**
     * @return array
     */
    private function getNonPublicMethods()
    {
        return array_map(
            function ($method) {
                return $method->getName();
            },
            array_filter($this->mockery_getMethods(), function ($method) {
                return !$method->isPublic();
            })
        );
    }
}
Exception.php000066400000001372151520666110007223 0ustar00<?php
/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mockery/blob/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 *
 * @category   Mockery
 * @package    Mockery
 * @copyright  Copyright (c) 2010-2014 Pádraic Brady (http://blog.astrumfutura.com)
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
 */

namespace Mockery;

class Exception extends \UnexpectedValueException
{
}
Container.php000066400000035362151520666110007215 0ustar00<?php
/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mockery/blob/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 *
 * @category   Mockery
 * @package    Mockery
 * @copyright  Copyright (c) 2010-2014 Pádraic Brady (http://blog.astrumfutura.com)
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
 */

namespace Mockery;

use Mockery\Generator\Generator;
use Mockery\Generator\MockConfigurationBuilder;
use Mockery\Loader\Loader as LoaderInterface;

class Container
{
    const BLOCKS = \Mockery::BLOCKS;

    /**
     * Store of mock objects
     *
     * @var array
     */
    protected $_mocks = array();

    /**
     * Order number of allocation
     *
     * @var int
     */
    protected $_allocatedOrder = 0;

    /**
     * Current ordered number
     *
     * @var int
     */
    protected $_currentOrder = 0;

    /**
     * Ordered groups
     *
     * @var array
     */
    protected $_groups = array();

    /**
     * @var Generator\Generator
     */
    protected $_generator;

    /**
     * @var LoaderInterface
     */
    protected $_loader;

    /**
     * @var array
     */
    protected $_namedMocks = array();

    public function __construct(Generator $generator = null, LoaderInterface $loader = null)
    {
        $this->_generator = $generator ?: \Mockery::getDefaultGenerator();
        $this->_loader = $loader ?: \Mockery::getDefaultLoader();
    }

    /**
     * Generates a new mock object for this container
     *
     * I apologies in advance for this. A God Method just fits the API which
     * doesn't require differentiating between classes, interfaces, abstracts,
     * names or partials - just so long as it's something that can be mocked.
     * I'll refactor it one day so it's easier to follow.
     *
     * @throws Exception\RuntimeException
     * @throws Exception
     * @return \Mockery\Mock
     */
    public function mock()
    {
        $expectationClosure = null;
        $quickdefs = array();
        $constructorArgs = null;
        $blocks = array();
        $args = func_get_args();

        if (count($args) > 1) {
            $finalArg = end($args);
            reset($args);
            if (is_callable($finalArg) && is_object($finalArg)) {
                $expectationClosure = array_pop($args);
            }
        }

        $builder = new MockConfigurationBuilder();

        foreach ($args as $k => $arg) {
            if ($arg instanceof MockConfigurationBuilder) {
                $builder = $arg;
                unset($args[$k]);
            }
        }
        reset($args);

        $builder->setParameterOverrides(\Mockery::getConfiguration()->getInternalClassMethodParamMaps());

        while (count($args) > 0) {
            $arg = current($args);
            // check for multiple interfaces
            if (is_string($arg) && strpos($arg, ',') && !strpos($arg, ']')) {
                $interfaces = explode(',', str_replace(' ', '', $arg));
                foreach ($interfaces as $i) {
                    if (!interface_exists($i, true) && !class_exists($i, true)) {
                        throw new \Mockery\Exception(
                            'Class name follows the format for defining multiple'
                            . ' interfaces, however one or more of the interfaces'
                            . ' do not exist or are not included, or the base class'
                            . ' (which you may omit from the mock definition) does not exist'
                        );
                    }
                }
                $builder->addTargets($interfaces);
                array_shift($args);

                continue;
            } elseif (is_string($arg) && substr($arg, 0, 6) == 'alias:') {
                $name = array_shift($args);
                $name = str_replace('alias:', '', $name);
                $builder->addTarget('stdClass');
                $builder->setName($name);
                continue;
            } elseif (is_string($arg) && substr($arg, 0, 9) == 'overload:') {
                $name = array_shift($args);
                $name = str_replace('overload:', '', $name);
                $builder->setInstanceMock(true);
                $builder->addTarget('stdClass');
                $builder->setName($name);
                continue;
            } elseif (is_string($arg) && substr($arg, strlen($arg)-1, 1) == ']') {
                $parts = explode('[', $arg);
                if (!class_exists($parts[0], true) && !interface_exists($parts[0], true)) {
                    throw new \Mockery\Exception('Can only create a partial mock from'
                    . ' an existing class or interface');
                }
                $class = $parts[0];
                $parts[1] = str_replace(' ', '', $parts[1]);
                $partialMethods = explode(',', strtolower(rtrim($parts[1], ']')));
                $builder->addTarget($class);
                $builder->setWhiteListedMethods($partialMethods);
                array_shift($args);
                continue;
            } elseif (is_string($arg) && (class_exists($arg, true) || interface_exists($arg, true))) {
                $class = array_shift($args);
                $builder->addTarget($class);
                continue;
            } elseif (is_string($arg)) {
                $class = array_shift($args);
                $builder->addTarget($class);
                continue;
            } elseif (is_object($arg)) {
                $partial = array_shift($args);
                $builder->addTarget($partial);
                continue;
            } elseif (is_array($arg) && !empty($arg) && array_keys($arg) !== range(0, count($arg) - 1)) {
                // if associative array
                if (array_key_exists(self::BLOCKS, $arg)) {
                    $blocks = $arg[self::BLOCKS];
                }
                unset($arg[self::BLOCKS]);
                $quickdefs = array_shift($args);
                continue;
            } elseif (is_array($arg)) {
                $constructorArgs = array_shift($args);
                continue;
            }

            throw new \Mockery\Exception(
                'Unable to parse arguments sent to '
                . get_class($this) . '::mock()'
            );
        }

        $builder->addBlackListedMethods($blocks);

        if (!is_null($constructorArgs)) {
            $builder->addBlackListedMethod("__construct"); // we need to pass through
        }

        if (!empty($partialMethods) && $constructorArgs === null) {
            $constructorArgs = array();
        }

        $config = $builder->getMockConfiguration();

        $this->checkForNamedMockClashes($config);

        $def = $this->getGenerator()->generate($config);

        if (class_exists($def->getClassName(), $attemptAutoload = false)) {
            $rfc = new \ReflectionClass($def->getClassName());
            if (!$rfc->implementsInterface("Mockery\MockInterface")) {
                throw new \Mockery\Exception\RuntimeException("Could not load mock {$def->getClassName()}, class already exists");
            }
        }

        $this->getLoader()->load($def);

        $mock = $this->_getInstance($def->getClassName(), $constructorArgs);
        $mock->mockery_init($this, $config->getTargetObject());

        if (!empty($quickdefs)) {
            $mock->shouldReceive($quickdefs)->byDefault();
        }
        if (!empty($expectationClosure)) {
            $expectationClosure($mock);
        }
        $this->rememberMock($mock);
        return $mock;
    }

    public function instanceMock()
    {
    }

    public function getLoader()
    {
        return $this->_loader;
    }

    public function getGenerator()
    {
        return $this->_generator;
    }

    /**
     * @param string $method
     * @return string|null
     */
    public function getKeyOfDemeterMockFor($method)
    {
        $keys = array_keys($this->_mocks);
        $match = preg_grep("/__demeter_{$method}$/", $keys);
        if (count($match) == 1) {
            $res = array_values($match);
            if (count($res) > 0) {
                return $res[0];
            }
        }
        return null;
    }

    /**
     * @return array
     */
    public function getMocks()
    {
        return $this->_mocks;
    }

    /**
     *  Tear down tasks for this container
     *
     * @throws \Exception
     * @return void
     */
    public function mockery_teardown()
    {
        try {
            $this->mockery_verify();
        } catch (\Exception $e) {
            $this->mockery_close();
            throw $e;
        }
    }

    /**
     * Verify the container mocks
     *
     * @return void
     */
    public function mockery_verify()
    {
        foreach ($this->_mocks as $mock) {
            $mock->mockery_verify();
        }
    }

    /**
     * Reset the container to its original state
     *
     * @return void
     */
    public function mockery_close()
    {
        foreach ($this->_mocks as $mock) {
            $mock->mockery_teardown();
        }
        $this->_mocks = array();
    }

    /**
     * Fetch the next available allocation order number
     *
     * @return int
     */
    public function mockery_allocateOrder()
    {
        $this->_allocatedOrder += 1;
        return $this->_allocatedOrder;
    }

    /**
     * Set ordering for a group
     *
     * @param mixed $group
     * @param int $order
     */
    public function mockery_setGroup($group, $order)
    {
        $this->_groups[$group] = $order;
    }

    /**
     * Fetch array of ordered groups
     *
     * @return array
     */
    public function mockery_getGroups()
    {
        return $this->_groups;
    }

    /**
     * Set current ordered number
     *
     * @param int $order
     * @return int The current order number that was set
     */
    public function mockery_setCurrentOrder($order)
    {
        $this->_currentOrder = $order;
        return $this->_currentOrder;
    }

    /**
     * Get current ordered number
     *
     * @return int
     */
    public function mockery_getCurrentOrder()
    {
        return $this->_currentOrder;
    }

    /**
     * Validate the current mock's ordering
     *
     * @param string $method
     * @param int $order
     * @throws \Mockery\Exception
     * @return void
     */
    public function mockery_validateOrder($method, $order, \Mockery\MockInterface $mock)
    {
        if ($order < $this->_currentOrder) {
            $exception = new \Mockery\Exception\InvalidOrderException(
                'Method ' . $method . ' called out of order: expected order '
                . $order . ', was ' . $this->_currentOrder
            );
            $exception->setMock($mock)
                ->setMethodName($method)
                ->setExpectedOrder($order)
                ->setActualOrder($this->_currentOrder);
            throw $exception;
        }
        $this->mockery_setCurrentOrder($order);
    }

    /**
     * Gets the count of expectations on the mocks
     *
     * @return int
     */
    public function mockery_getExpectationCount()
    {
        $count = 0;
        foreach ($this->_mocks as $mock) {
            $count += $mock->mockery_getExpectationCount();
        }
        return $count;
    }

    /**
     * Store a mock and set its container reference
     *
     * @param \Mockery\Mock
     * @return \Mockery\Mock
     */
    public function rememberMock(\Mockery\MockInterface $mock)
    {
        if (!isset($this->_mocks[get_class($mock)])) {
            $this->_mocks[get_class($mock)] = $mock;
        } else {
            /**
             * This condition triggers for an instance mock where origin mock
             * is already remembered
             */
            $this->_mocks[] = $mock;
        }
        return $mock;
    }

    /**
     * Retrieve the last remembered mock object, which is the same as saying
     * retrieve the current mock being programmed where you have yet to call
     * mock() to change it - thus why the method name is "self" since it will be
     * be used during the programming of the same mock.
     *
     * @return \Mockery\Mock
     */
    public function self()
    {
        $mocks = array_values($this->_mocks);
        $index = count($mocks) - 1;
        return $mocks[$index];
    }

    /**
     * Return a specific remembered mock according to the array index it
     * was stored to in this container instance
     *
     * @return \Mockery\Mock
     */
    public function fetchMock($reference)
    {
        if (isset($this->_mocks[$reference])) {
            return $this->_mocks[$reference];
        }
    }

    protected function _getInstance($mockName, $constructorArgs = null)
    {
        if ($constructorArgs !== null) {
            $r = new \ReflectionClass($mockName);
            return $r->newInstanceArgs($constructorArgs);
        }

        try {
            $instantiator = new Instantiator;
            $instance = $instantiator->instantiate($mockName);
        } catch (\Exception $ex) {
            $internalMockName = $mockName . '_Internal';

            if (!class_exists($internalMockName)) {
                eval("class $internalMockName extends $mockName {" .
                        'public function __construct() {}' .
                    '}');
            }

            $instance = new $internalMockName();
        }

        return $instance;
    }

    /**
     * Takes a class name and declares it
     *
     * @param string $fqcn
     */
    public function declareClass($fqcn)
    {
        if (false !== strpos($fqcn, '/')) {
            throw new \Mockery\Exception(
                'Class name contains a forward slash instead of backslash needed '
                . 'when employing namespaces'
            );
        }
        if (false !== strpos($fqcn, "\\")) {
            $parts = array_filter(explode("\\", $fqcn), function ($part) {
                return $part !== "";
            });
            $cl = array_pop($parts);
            $ns = implode("\\", $parts);
            eval(" namespace $ns { class $cl {} }");
        } else {
            eval(" class $fqcn {} ");
        }
    }

    protected function checkForNamedMockClashes($config)
    {
        $name = $config->getName();

        if (!$name) {
            return;
        }

        $hash = $config->getHash();

        if (isset($this->_namedMocks[$name])) {
            if ($hash !== $this->_namedMocks[$name]) {
                throw new \Mockery\Exception(
                    "The mock named '$name' has been already defined with a different mock configuration"
                );
            }
        }

        $this->_namedMocks[$name] = $hash;
    }
}
Expectation.php000066400000045314151520666110007554 0ustar00<?php
/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mockery/blob/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 *
 * @category   Mockery
 * @package    Mockery
 * @copyright  Copyright (c) 2010-2014 Pádraic Brady (http://blog.astrumfutura.com)
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
 */

namespace Mockery;

class Expectation implements ExpectationInterface
{

    /**
     * Mock object to which this expectation belongs
     *
     * @var object
     */
    protected $_mock = null;

    /**
     * Method name
     *
     * @var string
     */
    protected $_name = null;

    /**
     * Arguments expected by this expectation
     *
     * @var array
     */
    protected $_expectedArgs = array();

    /**
     * Count validator store
     *
     * @var array
     */
    protected $_countValidators = array();

    /**
     * The count validator class to use
     *
     * @var string
     */
    protected $_countValidatorClass = 'Mockery\CountValidator\Exact';

    /**
     * Actual count of calls to this expectation
     *
     * @var int
     */
    protected $_actualCount = 0;

    /**
     * Value to return from this expectation
     *
     * @var mixed
     */
    protected $_returnValue = null;

    /**
     * Array of return values as a queue for multiple return sequence
     *
     * @var array
     */
    protected $_returnQueue = array();

    /**
     * Array of closures executed with given arguments to generate a result
     * to be returned
     *
     * @var array
     */
    protected $_closureQueue = array();

    /**
     * Array of values to be set when this expectation matches
     *
     * @var array
     */
    protected $_setQueue = array();

    /**
     * Integer representing the call order of this expectation
     *
     * @var int
     */
    protected $_orderNumber = null;

    /**
     * Integer representing the call order of this expectation on a global basis
     *
     * @var int
     */
    protected $_globalOrderNumber = null;

    /**
     * Flag indicating that an exception is expected to be throw (not returned)
     *
     * @var bool
     */
    protected $_throw = false;

    /**
     * Flag indicating whether the order of calling is determined locally or
     * globally
     *
     * @var bool
     */
    protected $_globally = false;

    /**
     * Flag indicating we expect no arguments
     *
     * @var bool
     */
    protected $_noArgsExpectation = false;

    /**
     * Flag indicating if the return value should be obtained from the original
     * class method instead of returning predefined values from the return queue
     *
     * @var bool
     */
    protected $_passthru = false;

    /**
     * Constructor
     *
     * @param \Mockery\MockInterface $mock
     * @param string $name
     */
    public function __construct(\Mockery\MockInterface $mock, $name)
    {
        $this->_mock = $mock;
        $this->_name = $name;
    }

    /**
     * Return a string with the method name and arguments formatted
     *
     * @param string $name Name of the expected method
     * @param array $args List of arguments to the method
     * @return string
     */
    public function __toString()
    {
        return \Mockery::formatArgs($this->_name, $this->_expectedArgs);
    }

    /**
     * Verify the current call, i.e. that the given arguments match those
     * of this expectation
     *
     * @param array $args
     * @return mixed
     */
    public function verifyCall(array $args)
    {
        $this->validateOrder();
        $this->_actualCount++;
        if (true === $this->_passthru) {
            return $this->_mock->mockery_callSubjectMethod($this->_name, $args);
        }
        $return = $this->_getReturnValue($args);
        if ($return instanceof \Exception && $this->_throw === true) {
            throw $return;
        }
        $this->_setValues();
        return $return;
    }

    /**
     * Sets public properties with queued values to the mock object
     *
     * @param array $args
     * @return mixed
     */
    protected function _setValues()
    {
        $mockClass = get_class($this->_mock);
        $container = $this->_mock->mockery_getContainer();
        $mocks = $container->getMocks();
        foreach ($this->_setQueue as $name => &$values) {
            if (count($values) > 0) {
                $value = array_shift($values);
                foreach ($mocks as $mock) {
                    if (is_a($mock, $mockClass)) {
                        $mock->{$name} = $value;
                    }
                }
            }
        }
    }

    /**
     * Fetch the return value for the matching args
     *
     * @param array $args
     * @return mixed
     */
    protected function _getReturnValue(array $args)
    {
        if (count($this->_closureQueue) > 1) {
            return call_user_func_array(array_shift($this->_closureQueue), $args);
        } elseif (count($this->_closureQueue) > 0) {
            return call_user_func_array(current($this->_closureQueue), $args);
        } elseif (count($this->_returnQueue) > 1) {
            return array_shift($this->_returnQueue);
        } elseif (count($this->_returnQueue) > 0) {
            return current($this->_returnQueue);
        }

        $rm = $this->_mock->mockery_getMethod($this->_name);
        if ($rm && version_compare(PHP_VERSION, '7.0.0-dev') >= 0 && $rm->hasReturnType()) {
            $type = (string) $rm->getReturnType();
            switch ($type) {
                case '':       return;
                case 'void':   return;
                case 'string': return '';
                case 'int':    return 0;
                case 'float':  return 0.0;
                case 'bool':   return false;
                case 'array':  return array();

                case 'callable':
                case 'Closure':
                    return function () {
                    };

                case 'Traversable':
                case 'Generator':
                    // Remove eval() when minimum version >=5.5
                    $generator = eval('return function () { yield; };');
                    return $generator();

                default:
                    return \Mockery::mock($type);
            }
        }
    }

    /**
     * Checks if this expectation is eligible for additional calls
     *
     * @return bool
     */
    public function isEligible()
    {
        foreach ($this->_countValidators as $validator) {
            if (!$validator->isEligible($this->_actualCount)) {
                return false;
            }
        }
        return true;
    }

    /**
     * Check if there is a constraint on call count
     *
     * @return bool
     */
    public function isCallCountConstrained()
    {
        return (count($this->_countValidators) > 0);
    }

    /**
     * Verify call order
     *
     * @return void
     */
    public function validateOrder()
    {
        if ($this->_orderNumber) {
            $this->_mock->mockery_validateOrder((string) $this, $this->_orderNumber, $this->_mock);
        }
        if ($this->_globalOrderNumber) {
            $this->_mock->mockery_getContainer()
                ->mockery_validateOrder((string) $this, $this->_globalOrderNumber, $this->_mock);
        }
    }

    /**
     * Verify this expectation
     *
     * @return bool
     */
    public function verify()
    {
        foreach ($this->_countValidators as $validator) {
            $validator->validate($this->_actualCount);
        }
    }

    /**
     * Check if passed arguments match an argument expectation
     *
     * @param array $args
     * @return bool
     */
    public function matchArgs(array $args)
    {
        if (empty($this->_expectedArgs) && !$this->_noArgsExpectation) {
            return true;
        }
        $expected = is_array($this->_expectedArgs) ? count($this->_expectedArgs) : 0;
        if (count($args) !== $expected) {
            return false;
        }
        $argCount = count($args);
        for ($i=0; $i<$argCount; $i++) {
            $param =& $args[$i];
            if (!$this->_matchArg($this->_expectedArgs[$i], $param)) {
                return false;
            }
        }

        return true;
    }

    /**
     * Check if passed argument matches an argument expectation
     *
     * @param array $args
     * @return bool
     */
    protected function _matchArg($expected, &$actual)
    {
        if ($expected === $actual) {
            return true;
        }
        if (!is_object($expected) && !is_object($actual) && $expected == $actual) {
            return true;
        }
        if (is_string($expected) && !is_array($actual) && !is_object($actual)) {
            # push/pop an error handler here to to make sure no error/exception thrown if $expected is not a regex
            set_error_handler(function () {
            });
            $result = preg_match($expected, (string) $actual);
            restore_error_handler();

            if ($result) {
                return true;
            }
        }
        if (is_string($expected) && is_object($actual)) {
            $result = $actual instanceof $expected;
            if ($result) {
                return true;
            }
        }
        if ($expected instanceof \Mockery\Matcher\MatcherAbstract) {
            return $expected->match($actual);
        }
        if (is_a($expected, '\Hamcrest\Matcher') || is_a($expected, '\Hamcrest_Matcher')) {
            return $expected->matches($actual);
        }
        return false;
    }

    /**
     * Expected argument setter for the expectation
     *
     * @param mixed ...
     * @return self
     */
    public function with()
    {
        return $this->withArgs(func_get_args());
    }

    /**
     * Expected arguments for the expectation passed as an array
     *
     * @param array $args
     * @return self
     */
    public function withArgs(array $args)
    {
        if (empty($args)) {
            return $this->withNoArgs();
        }
        $this->_expectedArgs = $args;
        $this->_noArgsExpectation = false;
        return $this;
    }

    /**
     * Set with() as no arguments expected
     *
     * @return self
     */
    public function withNoArgs()
    {
        $this->_noArgsExpectation = true;
        $this->_expectedArgs = null;
        return $this;
    }

    /**
     * Set expectation that any arguments are acceptable
     *
     * @return self
     */
    public function withAnyArgs()
    {
        $this->_expectedArgs = array();
        return $this;
    }

    /**
     * Set a return value, or sequential queue of return values
     *
     * @param mixed ...
     * @return self
     */
    public function andReturn()
    {
        $this->_returnQueue = func_get_args();
        return $this;
    }

    /**
     * Return this mock, like a fluent interface
     *
     * @return self
     */
    public function andReturnSelf()
    {
        return $this->andReturn($this->_mock);
    }

    /**
     * Set a sequential queue of return values with an array
     *
     * @param array $values
     * @return self
     */
    public function andReturnValues(array $values)
    {
        call_user_func_array(array($this, 'andReturn'), $values);
        return $this;
    }

    /**
     * Set a closure or sequence of closures with which to generate return
     * values. The arguments passed to the expected method are passed to the
     * closures as parameters.
     *
     * @param callable ...
     * @return self
     */
    public function andReturnUsing()
    {
        $this->_closureQueue = func_get_args();
        return $this;
    }

    /**
     * Return a self-returning black hole object.
     *
     * @return self
     */
    public function andReturnUndefined()
    {
        $this->andReturn(new \Mockery\Undefined);
        return $this;
    }

    /**
     * Return null. This is merely a language construct for Mock describing.
     *
     * @return self
     */
    public function andReturnNull()
    {
        return $this;
    }

    /**
     * Set Exception class and arguments to that class to be thrown
     *
     * @param string $exception
     * @param string $message
     * @param int $code
     * @param Exception $previous
     * @return self
     */
    public function andThrow($exception, $message = '', $code = 0, \Exception $previous = null)
    {
        $this->_throw = true;
        if (is_object($exception)) {
            $this->andReturn($exception);
        } else {
            $this->andReturn(new $exception($message, $code, $previous));
        }
        return $this;
    }

    /**
     * Set Exception classes to be thrown
     *
     * @param array $exceptions
     * @return self
     */
    public function andThrowExceptions(array $exceptions)
    {
        $this->_throw = true;
        foreach ($exceptions as $exception) {
            if (!is_object($exception)) {
                throw new Exception('You must pass an array of exception objects to andThrowExceptions');
            }
        }
        return $this->andReturnValues($exceptions);
    }

    /**
     * Register values to be set to a public property each time this expectation occurs
     *
     * @param string $name
     * @param mixed $value
     * @return self
     */
    public function andSet($name, $value)
    {
        $values = func_get_args();
        array_shift($values);
        $this->_setQueue[$name] = $values;
        return $this;
    }

    /**
     * Alias to andSet(). Allows the natural English construct
     * - set('foo', 'bar')->andReturn('bar')
     *
     * @param string $name
     * @param mixed $value
     * @return self
     */
    public function set($name, $value)
    {
        return call_user_func_array(array($this, 'andSet'), func_get_args());
    }

    /**
     * Indicates this expectation should occur zero or more times
     *
     * @return self
     */
    public function zeroOrMoreTimes()
    {
        $this->atLeast()->never();
    }

    /**
     * Indicates the number of times this expectation should occur
     *
     * @param int $limit
     * @return self
     */
    public function times($limit = null)
    {
        if (is_null($limit)) {
            return $this;
        }
        $this->_countValidators[] = new $this->_countValidatorClass($this, $limit);
        $this->_countValidatorClass = 'Mockery\CountValidator\Exact';
        return $this;
    }

    /**
     * Indicates that this expectation is never expected to be called
     *
     * @return self
     */
    public function never()
    {
        return $this->times(0);
    }

    /**
     * Indicates that this expectation is expected exactly once
     *
     * @return self
     */
    public function once()
    {
        return $this->times(1);
    }

    /**
     * Indicates that this expectation is expected exactly twice
     *
     * @return self
     */
    public function twice()
    {
        return $this->times(2);
    }

    /**
     * Sets next count validator to the AtLeast instance
     *
     * @return self
     */
    public function atLeast()
    {
        $this->_countValidatorClass = 'Mockery\CountValidator\AtLeast';
        return $this;
    }

    /**
     * Sets next count validator to the AtMost instance
     *
     * @return self
     */
    public function atMost()
    {
        $this->_countValidatorClass = 'Mockery\CountValidator\AtMost';
        return $this;
    }

    /**
     * Shorthand for setting minimum and maximum constraints on call counts
     *
     * @param int $minimum
     * @param int $maximum
     */
    public function between($minimum, $maximum)
    {
        return $this->atLeast()->times($minimum)->atMost()->times($maximum);
    }

    /**
     * Indicates that this expectation must be called in a specific given order
     *
     * @param string $group Name of the ordered group
     * @return self
     */
    public function ordered($group = null)
    {
        if ($this->_globally) {
            $this->_globalOrderNumber = $this->_defineOrdered($group, $this->_mock->mockery_getContainer());
        } else {
            $this->_orderNumber = $this->_defineOrdered($group, $this->_mock);
        }
        $this->_globally = false;
        return $this;
    }

    /**
     * Indicates call order should apply globally
     *
     * @return self
     */
    public function globally()
    {
        $this->_globally = true;
        return $this;
    }

    /**
     * Setup the ordering tracking on the mock or mock container
     *
     * @param string $group
     * @param object $ordering
     * @return int
     */
    protected function _defineOrdered($group, $ordering)
    {
        $groups = $ordering->mockery_getGroups();
        if (is_null($group)) {
            $result = $ordering->mockery_allocateOrder();
        } elseif (isset($groups[$group])) {
            $result = $groups[$group];
        } else {
            $result = $ordering->mockery_allocateOrder();
            $ordering->mockery_setGroup($group, $result);
        }
        return $result;
    }

    /**
     * Return order number
     *
     * @return int
     */
    public function getOrderNumber()
    {
        return $this->_orderNumber;
    }

    /**
     * Mark this expectation as being a default
     *
     * @return self
     */
    public function byDefault()
    {
        $director = $this->_mock->mockery_getExpectationsFor($this->_name);
        if (!empty($director)) {
            $director->makeExpectationDefault($this);
        }
        return $this;
    }

    /**
     * Return the parent mock of the expectation
     *
     * @return \Mockery\MockInterface
     */
    public function getMock()
    {
        return $this->_mock;
    }

    /**
     * Flag this expectation as calling the original class method with the
     * any provided arguments instead of using a return value queue.
     *
     * @return self
     */
    public function passthru()
    {
        if ($this->_mock instanceof Mock) {
            throw new Exception(
                'Mock Objects not created from a loaded/existing class are '
                . 'incapable of passing method calls through to a parent class'
            );
        }
        $this->_passthru = true;
        return $this;
    }

    /**
     * Cloning logic
     *
     */
    public function __clone()
    {
        $newValidators = array();
        $countValidators = $this->_countValidators;
        foreach ($countValidators as $validator) {
            $newValidators[] = clone $validator;
        }
        $this->_countValidators = $newValidators;
    }

    public function getName()
    {
        return $this->_name;
    }
}
Matcher/HasValue.php000066400000002306151520666110010356 0ustar00<?php
/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mockery/blob/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 *
 * @category   Mockery
 * @package    Mockery
 * @copyright  Copyright (c) 2010-2014 Pádraic Brady (http://blog.astrumfutura.com)
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
 */

namespace Mockery\Matcher;

class HasValue extends MatcherAbstract
{

    /**
     * Check if the actual value matches the expected.
     *
     * @param mixed $actual
     * @return bool
     */
    public function match(&$actual)
    {
        return in_array($this->_expected, $actual);
    }

    /**
     * Return a string representation of this Matcher
     *
     * @return string
     */
    public function __toString()
    {
        $return = '<HasValue[' . (string) $this->_expected . ']>';
        return $return;
    }
}
Matcher/MustBe.php000066400000002357151520666110010053 0ustar00<?php
/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mockery/blob/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 *
 * @category   Mockery
 * @package    Mockery
 * @copyright  Copyright (c) 2010-2014 Pádraic Brady (http://blog.astrumfutura.com)
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
 */

namespace Mockery\Matcher;

class MustBe extends MatcherAbstract
{

    /**
     * Check if the actual value matches the expected.
     *
     * @param mixed $actual
     * @return bool
     */
    public function match(&$actual)
    {
        if (!is_object($actual)) {
            return $this->_expected === $actual;
        } else {
            return $this->_expected == $actual;
        }
    }

    /**
     * Return a string representation of this Matcher
     *
     * @return string
     */
    public function __toString()
    {
        return '<MustBe>';
    }
}
Matcher/AnyOf.php000066400000002470151520666110007664 0ustar00<?php
/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mockery/blob/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 *
 * @category   Mockery
 * @package    Mockery
 * @copyright  Copyright (c) 2010-2014 Pádraic Brady (http://blog.astrumfutura.com)
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
 */

namespace Mockery\Matcher;

class AnyOf extends MatcherAbstract
{
    /**
     * Check if the actual value does not match the expected (in this
     * case it's specifically NOT expected).
     *
     * @param mixed $actual
     * @return bool
     */
    public function match(&$actual)
    {
        foreach ($this->_expected as $exp) {
            if ($actual === $exp || $actual == $exp) {
                return true;
            }
        }
        return false;
    }

    /**
     * Return a string representation of this Matcher
     *
     * @return string
     */
    public function __toString()
    {
        return '<AnyOf>';
    }
}
Matcher/Contains.php000066400000003270151520666110010425 0ustar00<?php
/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mockery/blob/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 *
 * @category   Mockery
 * @package    Mockery
 * @copyright  Copyright (c) 2010-2014 Pádraic Brady (http://blog.astrumfutura.com)
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
 */

namespace Mockery\Matcher;

class Contains extends MatcherAbstract
{

    /**
     * Check if the actual value matches the expected.
     *
     * @param mixed $actual
     * @return bool
     */
    public function match(&$actual)
    {
        $values = array_values($actual);
        foreach ($this->_expected as $exp) {
            $match = false;
            foreach ($values as $val) {
                if ($exp === $val || $exp == $val) {
                    $match = true;
                    break;
                }
            }
            if ($match === false) {
                return false;
            }
        }
        return true;
    }

    /**
     * Return a string representation of this Matcher
     *
     * @return string
     */
    public function __toString()
    {
        $return = '<Contains[';
        $elements = array();
        foreach ($this->_expected as $v) {
            $elements[] = (string) $v;
        }
        $return .= implode(', ', $elements) . ']>';
        return $return;
    }
}
Matcher/Any.php000066400000002137151520666110007377 0ustar00<?php
/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mockery/blob/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 *
 * @category   Mockery
 * @package    Mockery
 * @copyright  Copyright (c) 2010-2014 Pádraic Brady (http://blog.astrumfutura.com)
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
 */

namespace Mockery\Matcher;

class Any extends MatcherAbstract
{

    /**
     * Check if the actual value matches the expected.
     *
     * @param mixed $actual
     * @return bool
     */
    public function match(&$actual)
    {
        return true;
    }

    /**
     * Return a string representation of this Matcher
     *
     * @return string
     */
    public function __toString()
    {
        return '<Any>';
    }
}
Matcher/MatcherAbstract.php000066400000002731151520666110011717 0ustar00<?php
/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mockery/blob/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 *
 * @category   Mockery
 * @package    Mockery
 * @copyright  Copyright (c) 2010-2014 Pádraic Brady (http://blog.astrumfutura.com)
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
 */

namespace Mockery\Matcher;

abstract class MatcherAbstract
{

    /**
     * The expected value (or part thereof)
     *
     * @var mixed
     */
    protected $_expected = null;

    /**
     * Set the expected value
     *
     * @param mixed $expected
     */
    public function __construct($expected = null)
    {
        $this->_expected = $expected;
    }

    /**
     * Check if the actual value matches the expected.
     * Actual passed by reference to preserve reference trail (where applicable)
     * back to the original method parameter.
     *
     * @param mixed $actual
     * @return bool
     */
    abstract public function match(&$actual);

    /**
     * Return a string representation of this Matcher
     *
     * @return string
     */
    abstract public function __toString();
}
Matcher/Type.php000066400000002717151520666110007575 0ustar00<?php
/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mockery/blob/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 *
 * @category   Mockery
 * @package    Mockery
 * @copyright  Copyright (c) 2010-2014 Pádraic Brady (http://blog.astrumfutura.com)
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
 */

namespace Mockery\Matcher;

class Type extends MatcherAbstract
{

    /**
     * Check if the actual value matches the expected.
     *
     * @param mixed $actual
     * @return bool
     */
    public function match(&$actual)
    {
        $function = 'is_' . strtolower($this->_expected);
        if (function_exists($function)) {
            return $function($actual);
        } elseif (is_string($this->_expected)
        && (class_exists($this->_expected) || interface_exists($this->_expected))) {
            return $actual instanceof $this->_expected;
        }
        return false;
    }

    /**
     * Return a string representation of this Matcher
     *
     * @return string
     */
    public function __toString()
    {
        return '<' . ucfirst($this->_expected) . '>';
    }
}
Matcher/Not.php000066400000002263151520666110007410 0ustar00<?php
/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mockery/blob/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 *
 * @category   Mockery
 * @package    Mockery
 * @copyright  Copyright (c) 2010-2014 Pádraic Brady (http://blog.astrumfutura.com)
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
 */

namespace Mockery\Matcher;

class Not extends MatcherAbstract
{

    /**
     * Check if the actual value does not match the expected (in this
     * case it's specifically NOT expected).
     *
     * @param mixed $actual
     * @return bool
     */
    public function match(&$actual)
    {
        return $actual !== $this->_expected;
    }

    /**
     * Return a string representation of this Matcher
     *
     * @return string
     */
    public function __toString()
    {
        return '<Not>';
    }
}
Matcher/Ducktype.php000066400000002563151520666110010443 0ustar00<?php
/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mockery/blob/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 *
 * @category   Mockery
 * @package    Mockery
 * @copyright  Copyright (c) 2010-2014 Pádraic Brady (http://blog.astrumfutura.com)
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
 */

namespace Mockery\Matcher;

class Ducktype extends MatcherAbstract
{

    /**
     * Check if the actual value matches the expected.
     *
     * @param mixed $actual
     * @return bool
     */
    public function match(&$actual)
    {
        if (!is_object($actual)) {
            return false;
        }
        foreach ($this->_expected as $method) {
            if (!method_exists($actual, $method)) {
                return false;
            }
        }
        return true;
    }

    /**
     * Return a string representation of this Matcher
     *
     * @return string
     */
    public function __toString()
    {
        return '<Ducktype[' . implode(', ', $this->_expected) . ']>';
    }
}
Matcher/NotAnyOf.php000066400000002473151520666110010350 0ustar00<?php
/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mockery/blob/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 *
 * @category   Mockery
 * @package    Mockery
 * @copyright  Copyright (c) 2010-2014 Pádraic Brady (http://blog.astrumfutura.com)
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
 */

namespace Mockery\Matcher;

class NotAnyOf extends MatcherAbstract
{
    /**
     * Check if the actual value does not match the expected (in this
     * case it's specifically NOT expected).
     *
     * @param mixed $actual
     * @return bool
     */
    public function match(&$actual)
    {
        foreach ($this->_expected as $exp) {
            if ($actual === $exp || $actual == $exp) {
                return false;
            }
        }
        return true;
    }

    /**
     * Return a string representation of this Matcher
     *
     * @return string
     */
    public function __toString()
    {
        return '<AnyOf>';
    }
}
Matcher/Closure.php000066400000002304151520666110010260 0ustar00<?php
/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mockery/blob/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 *
 * @category   Mockery
 * @package    Mockery
 * @copyright  Copyright (c) 2010-2014 Pádraic Brady (http://blog.astrumfutura.com)
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
 */

namespace Mockery\Matcher;

class Closure extends MatcherAbstract
{

    /**
     * Check if the actual value matches the expected.
     *
     * @param mixed $actual
     * @return bool
     */
    public function match(&$actual)
    {
        $closure = $this->_expected;
        $result = $closure($actual);
        return $result === true;
    }

    /**
     * Return a string representation of this Matcher
     *
     * @return string
     */
    public function __toString()
    {
        return '<Closure===true>';
    }
}
Matcher/Subset.php000066400000003045151520666110010114 0ustar00<?php
/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mockery/blob/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 *
 * @category   Mockery
 * @package    Mockery
 * @copyright  Copyright (c) 2010-2014 Pádraic Brady (http://blog.astrumfutura.com)
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
 */

namespace Mockery\Matcher;

class Subset extends MatcherAbstract
{

    /**
     * Check if the actual value matches the expected.
     *
     * @param mixed $actual
     * @return bool
     */
    public function match(&$actual)
    {
        foreach ($this->_expected as $k=>$v) {
            if (!array_key_exists($k, $actual)) {
                return false;
            }
            if ($actual[$k] !== $v) {
                return false;
            }
        }
        return true;
    }

    /**
     * Return a string representation of this Matcher
     *
     * @return string
     */
    public function __toString()
    {
        $return = '<Subset[';
        $elements = array();
        foreach ($this->_expected as $k=>$v) {
            $elements[] = $k . '=' . (string) $v;
        }
        $return .= implode(', ', $elements) . ']>';
        return $return;
    }
}
Matcher/HasKey.php000066400000002316151520666110010033 0ustar00<?php
/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mockery/blob/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 *
 * @category   Mockery
 * @package    Mockery
 * @copyright  Copyright (c) 2010-2014 Pádraic Brady (http://blog.astrumfutura.com)
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
 */

namespace Mockery\Matcher;

class HasKey extends MatcherAbstract
{

    /**
     * Check if the actual value matches the expected.
     *
     * @param mixed $actual
     * @return bool
     */
    public function match(&$actual)
    {
        return in_array($this->_expected, array_keys($actual));
    }

    /**
     * Return a string representation of this Matcher
     *
     * @return string
     */
    public function __toString()
    {
        $return = '<HasKey[' . (string) $this->_expected . ']>';
        return $return;
    }
}