📜 ⬆️ ⬇️

PHPUnit: a simple syntax for creating mock objects



  1. why not mockery
  2. main advantage - syntax
  3. moki - native
  4. creating stub objects
  5. mocking class properties
  6. mock injection
  7. convenient methods for working with Reflection
  8. how to add to the project


Why not mockery


PHPUnit is the standard, most common framework for writing unit tests in the PHP world. No wonder - he copes well with the responsibilities assigned to him. But if we talk about the standard syntax for creating mock-objects, many people complain about its some cumbersome. They offer various plugins for creating mocks, such as Mockery (I understand that this is not just a plugin).

However, I am sure that PHPUnit has a well-developed system for creating mocks to continue using it. PHPUnit is actively developing: mocking of traits, mocking of nonexistent classes for TDD were added not so long ago.
')
And this XPMock project is a way to simplify the syntax for creating mocks. It should be emphasized that XPMock does not create its own mocks, and does not make any wrappers over the mocks of PHPUnit. XPMock calls the same PHPUnit methods, thus creating the same Mocks, only slightly simpler.

The main advantage is syntax.


The standard syntax for creating a mock (stub object with three methods) in PHPUnit looks like this:

$mock = $this->getMockBuilder('MyClass') ->setMethods(['getBool', 'getNumber', 'getString']) ->disableOriginalConstructor() ->getMock(); $mock->expects($this->any()) ->method('getBool') ->will($this->returnValue(true)); $mock->expects($this->any()) ->method('getNumber') ->will($this->returnValue(1)); $mock->expects($this->any()) ->method('getString') ->will($this->returnValue('string')); 


Those who mock most of the dependencies in unit tests notice that the test code grows very quickly because of such constructions.

If you use XPMock, the creation of mock becomes much shorter:

 $this->mock('MyClass') ->getBool(true) ->getNumber(1) ->getString('string') ->new(); 


Moki - native


XPMock
- does not create its own moki
- does not make additional wrappers over mocks PHPUnit
- supports all native PHPUnit constructs

For example,

 $mock->getNumber($this->once()) 


it's the same as writing

 $mock->expects($this->once()) ->method('getNumber') ->will($this->returnValue(null)) 


Other examples of a short recording of commonly used constructions can be found here: github.com/ptrofimov/xpmock

Creating stub objects


Stub objects, or stub objects, are mock objects in which all methods by default override the actual methods and return null. In PHPUnit, in the syntax there is no division into mocks, stubs, and others like them. All artificial objects for testing are created using getMock or getMockBuilder.

In XPMock, a special stub method is included that returns a mock, for which all methods return null by default. This improves the readability of the code, and eliminates the need to call the setMethods method when creating real mocks.

Mock class properties


PHPUnit cannot mock class properties. XPMock too. However, it provides convenient methods for setting properties of the created mock via Reflection. The assignments specified when creating the mock will be executed immediately after calling the new constructor method.

 $this->mock('MyClass') ->__set('property', $value) ->new(); 


You can use the familiar syntax of setting properties without using magic methods.

Mock injection


Very often, when creating mocks, they need to be immediately embedded into other objects. For example, create a singleton instance and embed a reference to it in a static instance variable of the same class. This is usually done via Reflection. XPMock and here provides a convenient syntax for such actions.

 $this->mock('MyClass') ->injectTo($object, 'property') ->new(); 


Convenient methods for working with Reflection


XPMock provides a common short syntax for working with objects via Reflection.

For example, to get a private property of an object, you usually need to write this:

 $property = new \ReflectionProperty('MyClass', 'property'); $property->setAccessible(true); $value = $property->getValue($object); 


With XPMock you can do it like this:

 $value = $this->reflect('MyClass')->property; 


With this syntax, you can get the values ​​of closed / open static / non-static properties of objects, as well as call private methods.

How to add to the project


XPMock is easily integrated into existing tests and does not interfere with the native syntax for creating mocks PHPUnit.

Option 1. Add XPMock trait to an existing test (suitable for PHP> = 5.4)

 class MyTestCase extends \PHPUnit_Framework_TestCase { use \Xpmock\TestCaseTrait; } 


Option 2. Inherit the test class from the corresponding XPMock class (suitable for PHP> = 5.3)

 class MyTestCase extends \Xpmock\TestCase { } 


Adding XPMock to a project is very simple - through the composer dependency manager. Installation instructions for 2 steps here - github.com/ptrofimov/xpmock#installation

Source: https://habr.com/ru/post/183010/


All Articles