├── .gitignore ├── .travis.yml ├── README.md ├── composer.json ├── phpunit.xml ├── src └── Xpmock │ ├── Base.php │ ├── MockAdjuster.php │ ├── MockWriter.php │ ├── Reflection.php │ ├── TestCase.php │ └── TestCaseTrait.php └── tests ├── .gitignore ├── Xpmock ├── ReflectionTest.php ├── TestCaseTraitTest.php └── UsageTest.php └── stubs ├── AbstractClass.php └── Usage.php /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | vendor 3 | composer.lock 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | 3 | php: 4 | - 5.3 5 | - 5.4 6 | 7 | before_script: 8 | - COMPOSER_ROOT_VERSION=dev-master composer --prefer-source --dev install 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # xpmock 2 | 3 | [![Build Status](https://travis-ci.org/ptrofimov/xpmock.png?branch=master)](https://travis-ci.org/ptrofimov/xpmock) 4 | [![Latest Stable Version](https://poser.pugx.org/ptrofimov/xpmock/v/stable.png)](https://packagist.org/packages/ptrofimov/xpmock) 5 | [![Total Downloads](https://poser.pugx.org/ptrofimov/xpmock/downloads.png)](https://packagist.org/packages/ptrofimov/xpmock) 6 | 7 | Introduction [[in English]](http://ptrofimov.github.io/) [[на русском]](http://habrahabr.ru/post/183010/) 8 | 9 | **!!! New version 1.1.5: [multiple improvements](https://github.com/ptrofimov/xpmock#new)** 10 | 11 | PHPUnit is standard testing framework in PHP world. 12 | No wonder - it is nifty. 13 | But speaking about way of mocking objects in PHPUnit many people complain on a bit redundant syntax. 14 | They suggest many addons for PHPUnit to create mocks like Mockery (I know this is not just addon). 15 | 16 | But I am sure PHPUnit has well-developed mocking system. 17 | And this project XPMock is a way to simplify this syntax a bit. 18 | I need to underline that XPMock doesn't create some own mock objects. 19 | XPMock just calls the same PHPUnit methods creating the same native mocks but much simpler. 20 | 21 | ### Write this 22 | ```php 23 | $this->mock('MyClass') 24 | ->getBool(true) 25 | ->getNumber(1) 26 | ->getString('string') 27 | ->new(); 28 | ``` 29 | ### instead of that 30 | ```php 31 | $mock = $this->getMockBuilder('MyClass') 32 | ->setMethods(['getBool', 'getNumber', 'getString']) 33 | ->disableOriginalConstructor() 34 | ->getMock(); 35 | $mock->expects($this->any()) 36 | ->method('getBool') 37 | ->will($this->returnValue(true)); 38 | $mock->expects($this->any()) 39 | ->method('getNumber') 40 | ->will($this->returnValue(1)); 41 | $mock->expects($this->any()) 42 | ->method('getString') 43 | ->will($this->returnValue('string')); 44 | ``` 45 | 46 | Tool generates full-functional native PHPUnit mocks. 47 | 48 | ## Syntax short description 49 | 50 | ```php 51 | 52 | // init mock writer 53 | 54 | $this->mock('MyClass') // init mock (all methods are real by default) 55 | 56 | // mock methods 57 | 58 | // $mock->expects($this->any())->method('getNumber')->will($this->returnValue(null)) 59 | ->getNumber() 60 | // $mock->expects($this->any())->method('getNumber')->will($this->returnValue(1)) 61 | ->getNumber(1) 62 | // $mock::staticExpects($this->any())->method('getNumber')->will($this->returnValue(1)) 63 | ->getNumber(1) 64 | // $mock->expects($this->any())->method('getNumber')->will($this->returnValue(1)) 65 | ->getNumber($this->returnValue(1)) 66 | // $mock->expects($this->once())->method('getNumber')->will($this->returnValue(null)) 67 | ->getNumber($this->once()) 68 | // $mock->expects($this->once())->method('getNumber')->will($this->returnValue(1)) 69 | ->getNumber(1, $this->once()) 70 | // $mock->expects($this->at(0))->method('getNumber')->will($this->returnValue(1)) 71 | // $mock->expects($this->at(1))->method('getNumber')->will($this->returnValue(2)) 72 | ->getNumber(1, $this->at(0)) 73 | ->getNumber(2, $this->at(1)) 74 | // $mock->expects($this->once())->method('getNumber')->with(1,2,3)->will($this->returnValue(null)) 75 | ->getNumber([1,2,3], $this->once()) 76 | // $mock->expects($this->any())->method('getNumber')->with(1,2,3)->will($this->returnValue(1)) 77 | ->getNumber([1,2,3], 1) 78 | // $mock->expects($this->once())->method('getNumber')->with(1,2,3)->will($this->returnValue(1)) 79 | ->getNumber([1,2,3], 1, $this->once()) 80 | // $mock->expects($this->any())->method('getNumber')->will($this->returnCallback(function(){})) 81 | ->getNumber(function(){}) 82 | // $mock->expects($this->any())->method('getNumber')->will($this->throwException(new \Exception(''))) 83 | ->getNumber(new \Exception('')) 84 | 85 | // create mock 86 | 87 | // $this->getMockBuilder('MyClass')->disableOriginalConstructor()->getMock() 88 | ->new() 89 | // $this->getMockBuilder('MyClass')->setConstructorArgs([1,2,3])->getMock() 90 | ->new(1, 2, 3) 91 | ``` 92 | 93 | ## Handy reflection methods 94 | 95 | ```php 96 | 97 | // get value of any property: static/non-static, public/protected/private 98 | 99 | $value = $this->reflect('MyClass')->property; // class name (only static) 100 | $value = $this->reflect(new MyClass())->property; // object 101 | 102 | // set value of any property: static/non-static, public/protected/private property 103 | 104 | $this->reflect('MyClass')->property = $value; // class name (only static) 105 | $this->reflect(new MyClass())->property = $value; // object 106 | $this->reflect(new MyClass()) 107 | ->__set('property1', $value1) 108 | ->__set('property2', $value2); // chain 109 | 110 | // call any method: static/non-static, public/protected/private 111 | 112 | $this->reflect('MyClass')->method($arg); // class name (only static) 113 | $this->reflect(new MyClass())->method($arg); // object 114 | 115 | ``` 116 | 117 | ## Installation 118 | 119 | 1. If you don't have composer, [install it](http://getcomposer.org) 120 | 2. Add xpmock to your project 121 | ``` 122 | composer require ptrofimov/xpmock:dev-master 123 | ``` 124 | 125 | ## Usage 126 | 127 | Option 1. Add trait to existing test case: 128 | ```php 129 | class MyTestCase extends \PHPUnit_Framework_TestCase 130 | { 131 | use \Xpmock\TestCaseTrait; 132 | } 133 | ``` 134 | OR Option 2. Extend your test case from xpmock's one: 135 | ```php 136 | class MyTestCase extends \Xpmock\TestCase 137 | { 138 | 139 | } 140 | ``` 141 | 142 | ## NEW 143 | 144 | 1. If you need to create object with some methods and classname doesn't matter, you could easily do it like this: 145 | ```php 146 | $mock = $this->mock() 147 | ->getString('string') 148 | ->getNumber(function () { 149 | return 2 + 2; 150 | }) 151 | ->new(); 152 | ``` 153 | 154 | 2. Mocking static methods 155 | 3. Mocking abstract methods 156 | 4. Brief syntax to create mocks 157 | ```php 158 | $mock = $this->mock('MyClass', ['getNumber' => 1]); 159 | ``` 160 | 161 | 5. Special method this() inside each mock gives you possibility to change 162 | non-public properties and call non-public methods of mock via Xpmock\Reflection 163 | ```php 164 | $mock = $this->mock('MyClass')->new(); 165 | $mock->this()->protectedProperty = 'value'; 166 | $mock->this()->protectedMethod(); 167 | ``` 168 | 169 | 6. You can use $this pointer inside your fake methods 170 | ```php 171 | $mock = $this->mock('MyClass', 172 | [ 173 | 'property' => 1, 174 | 'getProperty' => function () { 175 | return $this->property; 176 | }, 177 | ] 178 | ); 179 | ``` 180 | 181 | 7. It is easy now to create mocks all methods of which return some value, for example null (stub) 182 | ```php 183 | $mock = $this->mock('MyClass', null); 184 | ``` 185 | 186 | 8. Very expected: now it is possible to adjust mocks after creation with magic method mock() 187 | ```php 188 | $myClass = $this->mock('MyClass', null); 189 | $myClass->getNumber(); // null 190 | $myClass->mock() 191 | ->getNumber(1); 192 | $myClass->getNumber(); // 1 193 | ``` 194 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ptrofimov/xpmock", 3 | "description": "PHPUnit: simple syntax to create mock-objects", 4 | "license": "MIT", 5 | "require": { 6 | "php": ">=5.3.0" 7 | }, 8 | "require-dev": { 9 | "phpunit/phpunit": "3.7.*" 10 | }, 11 | "autoload": { 12 | "psr-0": { 13 | "Xpmock": "src" 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /phpunit.xml: -------------------------------------------------------------------------------- 1 | 19 | 20 | 21 | ./tests 22 | 23 | 24 | 25 | 26 | ./src 27 | 28 | 29 | 30 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /src/Xpmock/Base.php: -------------------------------------------------------------------------------- 1 | $method, 53 | 'expects' => $expects, 54 | 'with' => $with, 55 | 'will' => $will, 56 | ); 57 | } 58 | 59 | protected function addMethodExpectation(\ReflectionClass $reflection, MockObject $mock, array $expectation) 60 | { 61 | if (is_null($expectation['will'])) { 62 | return; 63 | } 64 | $expect = $reflection->hasMethod($expectation['method']) 65 | && $reflection->getMethod($expectation['method'])->isStatic() 66 | ? $mock::staticExpects($expectation['expects']) 67 | : $mock->expects($expectation['expects']); 68 | $expect->method($expectation['method']) 69 | ->will( 70 | $expectation['will'] instanceof \Closure 71 | ? PhpUnitTestCase::returnCallback( 72 | version_compare(PHP_VERSION, '5.4.0', '>=') && !version_compare(PHP_VERSION, '7.0.0', '>=') ? $expectation['will']->bindTo($mock, $reflection->getName()) : $expectation['will'] 73 | ) : $expectation['will'] 74 | ); 75 | if (!is_null($expectation['with'])) { 76 | call_user_func_array(array($expect, 'with'), $expectation['with']); 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/Xpmock/MockAdjuster.php: -------------------------------------------------------------------------------- 1 | mock = $mock; 19 | $this->reflection = $reflection; 20 | } 21 | 22 | /** @return self */ 23 | public function __call($method, array $args) 24 | { 25 | $this->addMethodExpectation($this->reflection, $this->mock, $this->parseMockMethodArgs($method, $args)); 26 | 27 | return $this; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Xpmock/MockWriter.php: -------------------------------------------------------------------------------- 1 | className = (string) $className; 25 | $this->testCase = $testCase; 26 | $reflection = new \ReflectionClass($this->className); 27 | if (!is_array($object)) { 28 | $methods = array(); 29 | foreach ($reflection->getMethods(\ReflectionMethod::IS_PUBLIC) as $method) { 30 | $methods[$method->getName()] = $object; 31 | } 32 | $object = $methods; 33 | } 34 | foreach ($object as $key => $value) { 35 | if ($reflection->hasProperty($key)) { 36 | $this->properties[$key] = $value; 37 | } else { 38 | $this->addMethod($key, array($value)); 39 | } 40 | } 41 | } 42 | 43 | /** @return self|MockObject */ 44 | public function __call($method, array $args) 45 | { 46 | return $method == 'new' 47 | ? $this->buildMock($args) 48 | : $this->addMethod($method, $args); 49 | } 50 | 51 | /** @return MockObject */ 52 | private function buildMock(array $args) 53 | { 54 | $mockBuilder = $this->testCase->getMockBuilder($this->className); 55 | $mockBuilder->setMethods( 56 | array_merge($this->extractMethods(), array('this', 'mock')) 57 | ); 58 | if ($args) { 59 | $mockBuilder->setConstructorArgs($args); 60 | } else { 61 | $mockBuilder->disableOriginalConstructor(); 62 | } 63 | $mock = $mockBuilder->getMock(); 64 | $reflection = new \ReflectionClass($this->className); 65 | foreach ($this->items as $item) { 66 | $this->addMethodExpectation($reflection, $mock, $item); 67 | } 68 | $mock->expects(TestCase::any()) 69 | ->method('this') 70 | ->will(TestCase::returnValue(new Reflection($mock))); 71 | $mock->expects(TestCase::any()) 72 | ->method('mock') 73 | ->will(TestCase::returnValue(new MockAdjuster($mock, $reflection))); 74 | foreach ($this->properties as $key => $value) { 75 | $mock->this()->{$key} = $value; 76 | } 77 | 78 | return $mock; 79 | } 80 | 81 | /** @return self */ 82 | private function addMethod($method, array $args) 83 | { 84 | $this->items[] = $this->parseMockMethodArgs($method, $args); 85 | 86 | return $this; 87 | } 88 | 89 | /** 90 | * Extract methods from items 91 | * 92 | * @return array Unique method names 93 | */ 94 | private function extractMethods() 95 | { 96 | $methods = array(); 97 | foreach ($this->items as $item) { 98 | $methods[$item['method']] = true; 99 | } 100 | 101 | return array_keys($methods); 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /src/Xpmock/Reflection.php: -------------------------------------------------------------------------------- 1 | class, $this->object) = is_object($classOrObject) 14 | ? array(get_class($classOrObject), $classOrObject) 15 | : array((string) $classOrObject, null); 16 | } 17 | 18 | public function __get($key) 19 | { 20 | $property = new \ReflectionProperty($this->class, $key); 21 | if (!$property->isPublic()) { 22 | $property->setAccessible(true); 23 | } 24 | 25 | return $property->isStatic() 26 | ? $property->getValue() 27 | : $property->getValue($this->object); 28 | } 29 | 30 | public function __set($key, $value) 31 | { 32 | $property = new \ReflectionProperty($this->class, $key); 33 | if (!$property->isPublic()) { 34 | $property->setAccessible(true); 35 | } 36 | $property->isStatic() 37 | ? $property->setValue($value) 38 | : $property->setValue($this->object, $value); 39 | 40 | return $this; 41 | } 42 | 43 | public function __call($methodName, array $args) 44 | { 45 | $method = new \ReflectionMethod($this->class, $methodName); 46 | if (!$method->isPublic()) { 47 | $method->setAccessible(true); 48 | } 49 | return $method->isStatic() 50 | ? $method->invokeArgs(null, $args) 51 | : $method->invokeArgs($this->object, $args); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/Xpmock/TestCase.php: -------------------------------------------------------------------------------- 1 | new() : $mockWriter; 17 | } 18 | 19 | /** 20 | * @param string|object $classOrObject 21 | * 22 | * @return Reflection 23 | */ 24 | public function reflect($classOrObject) 25 | { 26 | return new Reflection($classOrObject); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/Xpmock/TestCaseTrait.php: -------------------------------------------------------------------------------- 1 | new() : $mockWriter; 17 | } 18 | 19 | /** 20 | * @param string|object $classOrObject 21 | * 22 | * @return Reflection 23 | */ 24 | public function reflect($classOrObject) 25 | { 26 | return new Reflection($classOrObject); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /tests/.gitignore: -------------------------------------------------------------------------------- 1 | report 2 | -------------------------------------------------------------------------------- /tests/Xpmock/ReflectionTest.php: -------------------------------------------------------------------------------- 1 | publicProperty = 1; 16 | self::$publicStaticProperty = 2; 17 | $this->privateProperty = 3; 18 | self::$privateStaticProperty = 4; 19 | } 20 | 21 | public function testGetProperty() 22 | { 23 | $this->assertSame( 24 | self::$publicStaticProperty, 25 | $this->reflect(__CLASS__)->publicStaticProperty 26 | ); 27 | $this->assertSame( 28 | self::$privateStaticProperty, 29 | $this->reflect(__CLASS__)->privateStaticProperty 30 | ); 31 | $this->assertSame( 32 | $this->publicProperty, 33 | $this->reflect($this)->publicProperty 34 | ); 35 | $this->assertSame( 36 | self::$publicStaticProperty, 37 | $this->reflect($this)->publicStaticProperty 38 | ); 39 | $this->assertSame( 40 | $this->privateProperty, 41 | $this->reflect($this)->privateProperty 42 | ); 43 | $this->assertSame( 44 | self::$privateStaticProperty, 45 | $this->reflect($this)->privateStaticProperty 46 | ); 47 | } 48 | 49 | public function testSetProperty() 50 | { 51 | $this->reflect(__CLASS__)->publicStaticProperty = 5; 52 | $this->assertSame(5, self::$publicStaticProperty); 53 | $this->reflect(__CLASS__)->privateStaticProperty = 5; 54 | $this->assertSame(5, self::$privateStaticProperty); 55 | $this->reflect($this)->publicProperty = 5; 56 | $this->assertSame(5, $this->publicProperty); 57 | $this->reflect($this)->publicStaticProperty = 5; 58 | $this->assertSame(5, self::$publicStaticProperty); 59 | $this->reflect($this)->privateProperty = 5; 60 | $this->assertSame(5, $this->privateProperty); 61 | $this->reflect($this)->privateStaticProperty = 5; 62 | $this->assertSame(5, self::$privateStaticProperty); 63 | } 64 | 65 | public function publicMethod($number) 66 | { 67 | return $number + 1; 68 | } 69 | 70 | private function privateMethod($number) 71 | { 72 | return $number + 2; 73 | } 74 | 75 | public static function publicStaticMethod($number) 76 | { 77 | return $number + 3; 78 | } 79 | 80 | private static function privateStaticMethod($number) 81 | { 82 | return $number + 4; 83 | } 84 | 85 | public function testCallMethod() 86 | { 87 | $this->assertSame(4, $this->reflect(__CLASS__)->publicStaticMethod(1)); 88 | $this->assertSame(5, $this->reflect(__CLASS__)->privateStaticMethod(1)); 89 | $this->assertSame(2, $this->reflect($this)->publicMethod(1)); 90 | $this->assertSame(3, $this->reflect($this)->privateMethod(1)); 91 | $this->assertSame(4, $this->reflect($this)->publicStaticMethod(1)); 92 | $this->assertSame(5, $this->reflect($this)->privateStaticMethod(1)); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /tests/Xpmock/TestCaseTraitTest.php: -------------------------------------------------------------------------------- 1 | isPublic()) { 15 | $property->setAccessible(true); 16 | } 17 | return $property->isStatic() 18 | ? $property->getValue($classOrObject) 19 | : $property->getValue(); 20 | } 21 | 22 | public function testMock() 23 | { 24 | $mockWriter = $this->mock('Stubs\Usage'); 25 | 26 | $this->assertInstanceOf('Xpmock\MockWriter', $mockWriter); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /tests/Xpmock/UsageTest.php: -------------------------------------------------------------------------------- 1 | __phpunit_cleanup(); 12 | } 13 | 14 | /** @return \Stubs\Usage */ 15 | private function mockUsage() 16 | { 17 | return $this->mock('Stubs\Usage'); 18 | } 19 | 20 | public function testMock() 21 | { 22 | $mock = $this->mockUsage(); 23 | 24 | $this->assertInstanceOf('Xpmock\MockWriter', $mock); 25 | } 26 | 27 | public function testReturnValue() 28 | { 29 | $mock = $this->mockUsage() 30 | ->getNumber(123) 31 | ->new(); 32 | 33 | $this->assertEquals(123, $mock->getNumber()); 34 | } 35 | 36 | public function testReturnNativeValue() 37 | { 38 | $mock = $this->mockUsage() 39 | ->getNumber($this->returnValue(112)) 40 | ->new(); 41 | 42 | $this->assertEquals(112, $mock->getNumber()); 43 | } 44 | 45 | public function testReturnCallback() 46 | { 47 | $mock = $this->mockUsage() 48 | ->getNumber( 49 | function () { 50 | return 156; 51 | } 52 | ) 53 | ->new(); 54 | 55 | $this->assertSame(156, $mock->getNumber()); 56 | } 57 | 58 | /** 59 | * @expectedException \LogicException 60 | */ 61 | public function testReturnThrowException() 62 | { 63 | $mock = $this->mockUsage() 64 | ->getNumber(new \LogicException()) 65 | ->new(); 66 | 67 | $mock->getNumber(); 68 | } 69 | 70 | public function testExpectsOnce() 71 | { 72 | $mock = $this->mockUsage() 73 | ->getNumber($this->once()) 74 | ->new(); 75 | 76 | try { 77 | $mock->getNumber(); 78 | $mock->getNumber(); 79 | $this->fail(); 80 | } catch (\PHPUnit_Framework_ExpectationFailedException $ex) { 81 | } 82 | 83 | $this->cleanupMock($mock); 84 | } 85 | 86 | public function testExpectsTwice() 87 | { 88 | $mock = $this->mockUsage() 89 | ->getNumber($this->exactly(2)) 90 | ->new(); 91 | 92 | try { 93 | $mock->getNumber(); 94 | $this->verifyMockObjects(); 95 | $this->fail(); 96 | } catch (\PHPUnit_Framework_ExpectationFailedException $ex) { 97 | } 98 | 99 | $this->cleanupMock($mock); 100 | } 101 | 102 | public function testExpectsAt() 103 | { 104 | $mock = $this->mockUsage() 105 | ->getNumber(1, $this->at(0)) 106 | ->getNumber(2, $this->at(1)) 107 | ->new(); 108 | 109 | $this->assertEquals(1, $mock->getNumber()); 110 | $this->assertEquals(2, $mock->getNumber()); 111 | } 112 | 113 | public function testWillExpects() 114 | { 115 | $mock = $this->mockUsage() 116 | ->getNumber(142, $this->once()) 117 | ->new(); 118 | 119 | $this->assertEquals(142, $mock->getNumber()); 120 | 121 | try { 122 | $mock->getNumber(); 123 | $this->fail(); 124 | } catch (\PHPUnit_Framework_ExpectationFailedException $ex) { 125 | } 126 | 127 | $this->cleanupMock($mock); 128 | } 129 | 130 | public function testWithWill() 131 | { 132 | $mock = $this->mockUsage() 133 | ->getNumber(array(1, 2, 3), 152) 134 | ->new(); 135 | 136 | $this->assertEquals(152, $mock->getNumber(1, 2, 3)); 137 | 138 | try { 139 | $mock->getNumber(); 140 | $this->fail(); 141 | } catch (\PHPUnit_Framework_ExpectationFailedException $ex) { 142 | } 143 | 144 | $this->cleanupMock($mock); 145 | } 146 | 147 | public function testWithExpects() 148 | { 149 | $mock = $this->mockUsage() 150 | ->getNumber(array(1, 2, 3), $this->once()) 151 | ->new(); 152 | 153 | $this->assertEquals(null, $mock->getNumber(1, 2, 3)); 154 | 155 | try { 156 | $mock->getNumber(1, 2, 3); 157 | $this->fail(); 158 | } catch (\PHPUnit_Framework_ExpectationFailedException $ex) { 159 | } 160 | 161 | $this->cleanupMock($mock); 162 | } 163 | 164 | /** 165 | * @expectedException \InvalidArgumentException 166 | */ 167 | public function testWithWillInvalid() 168 | { 169 | $this->mockUsage() 170 | ->getNumber('not_array', 1); 171 | } 172 | 173 | public function testWithWillExpects() 174 | { 175 | $mock = $this->mockUsage() 176 | ->getNumber(array(1, 2, 3), 1, $this->once()) 177 | ->new(); 178 | 179 | $this->assertEquals(1, $mock->getNumber(1, 2, 3)); 180 | 181 | try { 182 | $mock->getNumber(); 183 | $this->fail(); 184 | } catch (\PHPUnit_Framework_ExpectationFailedException $ex) { 185 | } 186 | 187 | try { 188 | $mock->getNumber(1, 2, 3); 189 | $this->fail(); 190 | } catch (\PHPUnit_Framework_ExpectationFailedException $ex) { 191 | } 192 | 193 | $this->cleanupMock($mock); 194 | } 195 | 196 | /** 197 | * @expectedException \InvalidArgumentException 198 | */ 199 | public function testWithWillExpectsInvalid() 200 | { 201 | $this->mockUsage() 202 | ->getNumber('not_array', 1, 1); 203 | } 204 | 205 | /** 206 | * @expectedException \RuntimeException 207 | * @expectedExceptionMessage Value 900 from constructor 208 | */ 209 | public function testNew() 210 | { 211 | $this->mockUsage() 212 | ->new(900); 213 | } 214 | 215 | public function testMockStdClass() 216 | { 217 | $mock = $this->mock() 218 | ->method1(1) 219 | ->method2(2) 220 | ->method3( 221 | function () { 222 | return 3; 223 | } 224 | )->new(); 225 | 226 | $this->assertInstanceOf('stdClass', $mock); 227 | $this->assertSame(1, $mock->method1()); 228 | $this->assertSame(2, $mock->method2()); 229 | $this->assertSame(3, $mock->method3()); 230 | } 231 | 232 | public function testMockStaticMethod() 233 | { 234 | $mock = $this->mockUsage() 235 | ->getString('fake string') 236 | ->new(); 237 | 238 | $this->assertSame('fake string', $mock->getString()); 239 | $this->assertSame('fake string', $mock::getString()); 240 | $this->assertSame(1, $mock->getNumber()); 241 | } 242 | 243 | public function testMockAbstractMethod() 244 | { 245 | $mock = $this->mock('Stubs\AbstractClass') 246 | ->getString('fake string') 247 | ->new(); 248 | 249 | $this->assertSame('fake string', $mock->getString()); 250 | $this->assertSame(2, $mock->getNumber()); 251 | } 252 | 253 | public function testBriefSyntax() 254 | { 255 | $mock = $this->mock( 256 | 'Stubs\Usage', 257 | array( 258 | 'getNumber' => 2, 259 | 'property' => 'fake property', 260 | 'getPropertyTwice' => function () { 261 | return $this->property . $this->property; 262 | }, 263 | ) 264 | ); 265 | 266 | $this->assertInstanceOf('Stubs\Usage', $mock); 267 | $this->assertSame(2, $mock->getNumber()); 268 | $this->assertSame('real string', $mock->getString()); 269 | $this->assertSame('fake property', $mock->getProperty()); 270 | if (version_compare(PHP_VERSION, '5.4.0', '>=')) { 271 | $this->assertSame('fake propertyfake property', $mock->getPropertyTwice()); 272 | } 273 | } 274 | 275 | public function testMethodThis() 276 | { 277 | $mock = $this->mockUsage() 278 | ->getNumber(2) 279 | ->new(); 280 | 281 | $this->assertSame('real string', $mock->getString()); 282 | $this->assertSame(2, $mock->getNumber()); 283 | $this->assertInstanceOf('Xpmock\Reflection', $mock->this()); 284 | $this->assertSame('real property', $mock->getProperty()); 285 | $mock->this()->property = 'fake property'; 286 | $this->assertSame('fake property', $mock->getProperty()); 287 | } 288 | 289 | public function testMockWhereAllMethodsReturnNull() 290 | { 291 | $mock = $this->mock('Stubs\Usage', null); 292 | 293 | $this->assertInstanceOf('Stubs\Usage', $mock); 294 | 295 | $this->assertNull($mock->getNumber()); 296 | $this->assertNull($mock->getString()); 297 | $this->assertNull($mock->getProperty()); 298 | $this->assertInstanceOf('Xpmock\Reflection', $mock->this()); 299 | $this->assertInstanceOf('Xpmock\MockAdjuster', $mock->mock()); 300 | } 301 | 302 | public function testAdjustAfterCreation() 303 | { 304 | $mock = $this->mock('Stubs\Usage', null); 305 | 306 | $this->assertNull($mock->getNumber()); 307 | $this->assertInstanceOf('Xpmock\MockAdjuster', $mock->mock()); 308 | 309 | $mock->mock() 310 | ->getNumber(3); 311 | 312 | $this->assertSame(3, $mock->getNumber()); 313 | } 314 | } 315 | -------------------------------------------------------------------------------- /tests/stubs/AbstractClass.php: -------------------------------------------------------------------------------- 1 | property; 26 | } 27 | } 28 | --------------------------------------------------------------------------------