tomazdurka/mocka


README

Travis Build Coverage Status

关于

Mocka 是一个干净、结构化但仍然非常灵活的模拟框架。它遵循面向对象的指导原则来创建模拟类、对象及其方法。模拟可以在创建或使用之前在运行时进行修改。它没有内置断言和期望框架 - 仍然可以很好地与任何测试框架集成。

安装

Mocka 在 packagist 上注册为 composer 包。

"tomaszdurka/mocka": "dev-master"

库使用

模拟类

$parentClassName = 'Exception';
$class = new ClassMock('MockedException', $parentClassName);
$exception1 = $class->newInstance(['exception message as constructor argument']);
$exception2 = $class->newInstanceWithoutConstructor();

创建模拟类的对象

$class = new ClassMock('MockedException', 'Exception');
$object = $class->newInstance('message');
$object->getMessage();

模拟方法

$class = new ClassMock('MockedException', 'Exception');
$class->mockMethod('getMessage');

// It's also possible to mock method only for generated object
$object = $class->newInstance('message');
$object->mockMethod('getMessage');

// It's possible to mock non-existent methods - they will work once mocked
$class->mockMethod('foo');

// It's also possible to mock static methods
$class->mockStaticMethod('bar');

修改方法行为

// Each method returned by any above mock methods return MethodMock object which can be manipulated
$class = new ClassMock('MockedException', 'Exception');
$mockedMethod = $class->mockMethod('getMessage');

// Set closure which will be executed when mocked method is called
$class->mockMethod('getMessage')->set(function () {
    return 'modified message';
});

// Set numbered callbacks
$class->mockMethod('getMessage')
    ->set(function () {
        return 'default message';
    })
    ->at(0, function () {
        return 'first message';
    })
    ->at(2, function () {
        return 'third message';
    });

// There is also shortcut to make method return certain value
$class->mockMethod('getMessages')->set('default')->at(0, 'first message');

// To check how many times method has been called simply use mocked method object
$mockedMethod = $class->mockMethod('getMessage');
// call method...
echo $mockedMethod->getCallCount();

模拟接口

$countableClass = new ClassMock('Collection', null, ['Countable']);

回退到原始方法

// It's a way to add extra behaviour to original method functionality
$class = new ClassMock('MockedException', 'Exception');
$object = $class->newInstanceWithoutConstructor();
$object->mockMethod('getMessage')->set(function() use ($object) {
    return 'prefix-' . $object->callOriginalMethod('getMessage', func_get_args());
});

与 PHPUnit 等测试框架一起使用

class TestCase extends \PHPUnit_Framework_TestCase {

    use \Mocka\MockaTrait;

    public function testFoo() {
        // When using mocka trait there are two shortcut methods added to create mocked objects
        $countableExceptionClass = $this->mockClass('DateTime', ['Countable']);
        $dateTimeObject = $this->mockObject('DateTime', ['29-12-1984']);
    }

    public function testMockingMethod() {
        $dateTimeObject = $this->mockObject('DateTime', ['29-12-1984']);
        $this->assertSame('29', $dateTimeObject->format('d'));
        $mockedFormatMethod = $dateTimeObject->mockMethod('format')->set('foo');
        $this->assertSame(0, $mockedFormatMethod->getCallCount());
        $this->assertSame('foo', $dateTimeObject->format('d'));
        $this->assertSame(1, $mockedFormatMethod->getCallCount());
    }

    public function testMethodAssertions() {
        $pdo = $this->mockClass('PDO')->newInstanceWithoutConstructor();
        $pdo->mockMethod('exec')->set(function ($statement) {
            $this->assertInstanceOf('PDOStatement', $statement);
        });
    }
}