qratorlabs / smocky
Mocking library based on runkit
Installs: 4 206
Dependents: 0
Suggesters: 0
Security: 0
Stars: 3
Watchers: 3
Forks: 0
Open Issues: 0
Requires
- php: ^7.1 || ^8.0
- phpunit/phpunit: ^9.6 || ^10.0 || ^11.0
Requires (Dev)
- phpstan/phpstan: ^1.10.58
- squizlabs/php_codesniffer: ^3.9.0
Suggests
- ext-runkit7: ^3.0
README
...and a bit more ;)
Goals
- easy mocking
- make any changes revertible
- revert changes automatically
Targets
There are several classes that will do the work:
- To use with PHPUnit:
MockedMethod
to mock method "globally" and use PHPUnit's*Mockers
-expects/willReturn/willReturnCallback/...
MockedFunction
- For class methods:
MockedClassMethod
to mock any class with closureUndefinedClassMethod
to make method disappear
- For class constants:
MockedClassConstant
UndefinedClassConstant
- For global constants:
MockedGlobalConstant
UndefinedGlobalConstant
- For functions (global or Namespaced):
MockedFunction
UndefinedFunction
Install
composer require --dev qratorlabs/smocky
MockedMethod
The main target is to make mocking static methods easy and feels-n-looks like using PHPUnit.
public function testSomeTest(): void { $methodMock = new MockedMethod($this, SomeClass::class, 'someMethod', once()); $methodMock->getMocker()->willReturn(10); SomeClass::someMethod(); // will return `10` SomeClass::someMethod(); // will cause error (expectation - one call) }
Note
There is a workaround that ensures that any (defined) children of class, which method is mocking, have its own method, defined by user or mocked (by Smocky - closure that calls parent).
Example for code that will fail without this workaround following code will end up with Segmentation fault: 11
class Base { public static function methodName() { return 'something'; } } class Child extends Base { } // simulating PHPUnit test case (new class('test') extends \PHPUnit\Framework\TestCase { public function test(): void { // child should instanced (or loaded any other way) $child = new Child(); // mocking method of base class $method = new MockedClassMethod(Base::class, 'methodName'); // at least one call should be made Base::methodName(); } })->run();
Trivia
Revertible changes
All changes are made revertible by using internal storage and __destruct
methods.
Drawbacks
Thing to keep in mind before using:
- Mocking anything will hit memory consumption (ex. to preserve changes)
- Mocking methods will hit performance (a bit)
- To mock static class we must check (and mock) children of mocking class