From 18e5044cafa8aeac57074e26012730507e8c5636 Mon Sep 17 00:00:00 2001 From: Robert Basic Date: Thu, 12 Feb 2015 08:31:17 +0100 Subject: [PATCH 1/3] Add cookbook entry about mocking hard dependencies Converted blog post from http://robertbasic.com/blog/mocking-hard-dependencies-with-mockery --- docs/cookbook/mocking_hard_dependencies.rst | 93 +++++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 docs/cookbook/mocking_hard_dependencies.rst diff --git a/docs/cookbook/mocking_hard_dependencies.rst b/docs/cookbook/mocking_hard_dependencies.rst new file mode 100644 index 000000000..6eb6aeea2 --- /dev/null +++ b/docs/cookbook/mocking_hard_dependencies.rst @@ -0,0 +1,93 @@ +.. index:: + single: Cookbook; Mocking Hard Dependencies + +Mocking Hard Dependencies +========================= + +One prerequisite to mock hard dependencies is that the code we are trying to test uses autoloading. + +Let's take the following code for an example: + +.. code-block:: php + + sendSomething($param); + return $externalService->getSomething(); + } + } + +The way we can test this without doing any changes to the code itself is by creating :doc:`instance mocks ` by using the ``overload`` prefix. + +.. code-block:: php + + shouldReceive('sendSomething') + ->once() + ->with($param); + $externalMock->shouldReceive('getSomething') + ->once() + ->andReturn('Tested!'); + + $service = new \App\Service(); + + $result = $service->callExternalService($param); + + $this->assertSame('Tested!', $result); + } + } + +If we run this test now, it should pass. Mockery does it's job and our ``App\Service`` will use the mocked external service instead of the real one. + +The problem whit this is when we want to, for example, test the ``App\Service\External`` itself, or if we use that class somewhere else in our tests. + +When Mockery overloads a class, because of how PHP works with files, that overloaded class file must not be included otherwise Mockery will throw a "class already exists" exception. This is where autoloading kicks in and makes our job a lot easier. + +To make this possible, we'll tell PHPUnit to run the tests that have overloaded classes in separate processes and to not preserve global state. That way we'll avoid having the overloaded class included more than once. Of course this has it's downsides as these tests will run slower. + +Our test example from above now becomes: + +.. code-block:: php + + shouldReceive('sendSomething') + ->once() + ->with($param); + $externalMock->shouldReceive('getSomething') + ->once() + ->andReturn('Tested!'); + + $service = new \App\Service(); + + $result = $service->callExternalService($param); + + $this->assertSame('Tested!', $result); + } + } From 5a0c311e1e99798a84ca9c050a95c593d0267f4b Mon Sep 17 00:00:00 2001 From: Robert Basic Date: Thu, 12 Feb 2015 08:33:17 +0100 Subject: [PATCH 2/3] add new cookbook entry to ToC --- docs/cookbook/index.rst | 1 + docs/cookbook/map.rst.inc | 1 + 2 files changed, 2 insertions(+) diff --git a/docs/cookbook/index.rst b/docs/cookbook/index.rst index 7e424e61c..a1fc36f96 100644 --- a/docs/cookbook/index.rst +++ b/docs/cookbook/index.rst @@ -6,5 +6,6 @@ Cookbook default_expectations detecting_mock_objects + mocking_hard_dependencies .. include:: map.rst.inc diff --git a/docs/cookbook/map.rst.inc b/docs/cookbook/map.rst.inc index 999f32492..e128f80d0 100644 --- a/docs/cookbook/map.rst.inc +++ b/docs/cookbook/map.rst.inc @@ -1,2 +1,3 @@ * :doc:`/cookbook/default_expectations` * :doc:`/cookbook/detecting_mock_objects` +* :doc:`/cookbook/mocking_hard_dependencies` From e8d622ddbd1cef58c7d39c87024fd57aff1275d6 Mon Sep 17 00:00:00 2001 From: Robert Basic Date: Thu, 12 Feb 2015 20:36:07 +0100 Subject: [PATCH 3/3] fix typos, thanks @padraic! --- docs/cookbook/mocking_hard_dependencies.rst | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/cookbook/mocking_hard_dependencies.rst b/docs/cookbook/mocking_hard_dependencies.rst index 6eb6aeea2..6d6271978 100644 --- a/docs/cookbook/mocking_hard_dependencies.rst +++ b/docs/cookbook/mocking_hard_dependencies.rst @@ -1,8 +1,8 @@ .. index:: single: Cookbook; Mocking Hard Dependencies -Mocking Hard Dependencies -========================= +Mocking Hard Dependencies (new Keyword) +======================================= One prerequisite to mock hard dependencies is that the code we are trying to test uses autoloading. @@ -51,13 +51,13 @@ The way we can test this without doing any changes to the code itself is by crea } } -If we run this test now, it should pass. Mockery does it's job and our ``App\Service`` will use the mocked external service instead of the real one. +If we run this test now, it should pass. Mockery does its job and our ``App\Service`` will use the mocked external service instead of the real one. -The problem whit this is when we want to, for example, test the ``App\Service\External`` itself, or if we use that class somewhere else in our tests. +The problem with this is when we want to, for example, test the ``App\Service\External`` itself, or if we use that class somewhere else in our tests. When Mockery overloads a class, because of how PHP works with files, that overloaded class file must not be included otherwise Mockery will throw a "class already exists" exception. This is where autoloading kicks in and makes our job a lot easier. -To make this possible, we'll tell PHPUnit to run the tests that have overloaded classes in separate processes and to not preserve global state. That way we'll avoid having the overloaded class included more than once. Of course this has it's downsides as these tests will run slower. +To make this possible, we'll tell PHPUnit to run the tests that have overloaded classes in separate processes and to not preserve global state. That way we'll avoid having the overloaded class included more than once. Of course this has its downsides as these tests will run slower. Our test example from above now becomes: