Blame | Letzte Änderung | Log anzeigen | RSS feed
.. index::single: Mocking; Partial MocksCreating Partial Mocks======================Partial mocks are useful when we only need to mock several methods of anobject leaving the remainder free to respond to calls normally (i.e. asimplemented). Mockery implements three distinct strategies for creatingpartials. Each has specific advantages and disadvantages so which strategy weuse will depend on our own preferences and the source code in need ofmocking.We have previously talked a bit about :ref:`creating-test-doubles-partial-test-doubles`,but we'd like to expand on the subject a bit here.#. Runtime partial test doubles#. Generated partial test doubles#. Proxied Partial MockRuntime partial test doubles----------------------------A runtime partial test double, also known as a passive partial mock, is a kindof a default state of being for a mocked object... code-block:: php$mock = \Mockery::mock('MyClass')->makePartial();With a runtime partial, we assume that all methods will simply defer to theparent class (``MyClass``) original methods unless a method call matches aknown expectation. If we have no matching expectation for a specific methodcall, that call is deferred to the class being mocked. Since the divisionbetween mocked and unmocked calls depends entirely on the expectations wedefine, there is no need to define which methods to mock in advance.See the cookbook entry on :doc:`../cookbook/big_parent_class` for an exampleusage of runtime partial test doubles.Generated Partial Test Doubles------------------------------A generated partial test double, also known as a traditional partial mock,defines ahead of time which methods of a class are to be mocked and which areto be left unmocked (i.e. callable as normal). The syntax for creatingtraditional mocks is:.. code-block:: php$mock = \Mockery::mock('MyClass[foo,bar]');In the above example, the ``foo()`` and ``bar()`` methods of MyClass will bemocked but no other MyClass methods are touched. We will need to defineexpectations for the ``foo()`` and ``bar()`` methods to dictate their mockedbehaviour.Don't forget that we can pass in constructor arguments since unmocked methodsmay rely on those!.. code-block:: php$mock = \Mockery::mock('MyNamespace\MyClass[foo]', array($arg1, $arg2));See the :ref:`creating-test-doubles-constructor-arguments` section to read upon them... note::Even though we support generated partial test doubles, we do not recommendusing them.Proxied Partial Mock--------------------A proxied partial mock is a partial of last resort. We may encounter a classwhich is simply not capable of being mocked because it has been marked asfinal. Similarly, we may find a class with methods marked as final. In such ascenario, we cannot simply extend the class and override methods to mock - weneed to get creative... code-block:: php$mock = \Mockery::mock(new MyClass);Yes, the new mock is a Proxy. It intercepts calls and reroutes them to theproxied object (which we construct and pass in) for methods which are notsubject to any expectations. Indirectly, this allows us to mock methodsmarked final since the Proxy is not subject to those limitations. The tradeoffshould be obvious - a proxied partial will fail any typehint checks for theclass being mocked since it cannot extend that class.Special Internal Cases----------------------All mock objects, with the exception of Proxied Partials, allows us to makeany expectation call to the underlying real class method using the ``passthru()``expectation call. This will return values from the real call and bypass anymocked return queue (which can simply be omitted obviously).There is a fourth kind of partial mock reserved for internal use. This isautomatically generated when we attempt to mock a class containing methodsmarked final. Since we cannot override such methods, they are simply leftunmocked. Typically, we don't need to worry about this but if we reallyreally must mock a final method, the only possible means is through a ProxiedPartial Mock. SplFileInfo, for example, is a common class subject to this formof automatic internal partial since it contains public final methods usedinternally.