|

Testing with Service Container

The backbone of Laravel is service container.  Service container is used for resolving classes and dependency injection.  Container comes as a standalone package, so you don’t have to have Laravel installed to use it.  Service container can be very handy when testing.  Let’s look at how we can use it .

Our basic set up consists of a route in web.php file:

OrdersController.php

ShopifyConnectorInterface is injected in index() method of the controller and looks like this:

ShopifyConnector class is bound as the interface implementation in AppServiceProvider.  ShopifConnector is instantiated using Shopify credentials stored in the configuration file.

Laravel’s service container will look at the interface, figure out that it is bound to ShopifyConnector, and instantiate it for us.  ShopifyConnector::getOrders()  makes a call to Shopify API and returns back orders.  For demonstration purposes we JSON encode them when returning.  In real life though, the orders will be passed to a view and the view will be returned from the controller.

The task is to test the code without hitting an actual API.  For that purposes we can create ShopifyConnectorFake and make it implement ShopifyConnectorInterface. 

Now in our test we can bind ShopifyConnectorFake to the interface.

As a side note: we use $this->withoutExceptionHandling() to avoid getting “Ooops” error display, because it is not very readable in the command line interface.

Most of the times we need to test not only successful result returned from ShopifyConnector, but also an error result.  We could create another ShopifyConnectorFake with its method getOrders() returning an error response.  And then another one, for a different response… Eventually we will end up with a lot of connector fakes.  A different approach would be to create a mock of ShopifyConnector and make its method return what we want.

First we create a mock of the ShopifyConnector class.  We need to disable original constructor, because in production code we are passing configuration parameters.  We define methods that we want to mock.  In our case it is one: getOrders(). There can be more though.  Also note only the methods you define will be mocked.  Other methods will behave as normal.  Then we tell phpunit we expect method getOrders() to be called once and return error response to us.  Now we can bind the mocked connector to ShopifyConnectorInterface as an instance.  In this case when container will be asked to resolve the interface, it will give us back the bound instance.

From the examples above we can see service container that comes with Laravel makes the application more testable and easier to test.

 

Resources:

Service Container

Laravel’s Dependency Injection Container in Depth

Chapter 9. Test Doubles

Share this article

Similar Posts

  • |

    Debugging Webhooks

    A webhook is an HTTP callback, that occurs when something happens (a resource changes its state). Webhooks provide a way to build event-driven apps, because you can be notified about changes. Since webhooks require a publicly accessible URL to function they can be hard to test from your local machine.  There are three main problems…

    Share this article
  • |

    Testing API Clients

    Since an API client is a boundary between your code and the outside world you should write as little code as possible to implement it. The client should strictly do its job by sending a request and returning a response. That is why we don’t really test the clients themselves but rather the code that processes the response from the client.

    Share this article
  • Stream Filter

    In php one can use filters with streams.  Sometimes it can become handy.  Let’s say you open a .csv file as a stream, but this file is tab separated.  Your program can can process coma separated csvs, but not tab separated.  This is a good use case for a stream filter, because it can make replacements…

    Share this article
  • | |

    Laravel Jenkins CI

    This article covers installation of Jenkins on Ubuntu server and its usage to continuously integrate a Laravel application.  Besides LAMP/LEMP stack we need to install Java, Git, Composer, and Node to successfully use Jenkins. Before starting to install this software, let’s take care of miscellaneous  stuff. Miscellaneous (can skip this). Create mysql user and database….

    Share this article
  • Upload to FTP with PHP

    $fp = fopen(‘https://www.example.com/pdfdoc’, ‘r’); $user = “sammy”; $pass = “password”; $ftp_server = “192.168.10.10”; //should be wrapped in try catch to properly handle errors $ftp_conn = ftp_ssl_connect($ftp_server); $login = ftp_login($ftp_conn, $user, $pass); ftp_chdir($ftp_conn, ‘path/to/folder’); //can also use ftp_pwd ftp_pasv($ftp_conn, true); //passive mode ftp_fput($ftp_conn, “mydocument.pdf”, $fp, FTP_BINARY); fclose($fp); ftp_close($ftp_conn); Above code can be used to upload a…

    Share this article
  • |

    Composer: Path Repositories

    When working on a php package it is inconvenient to push the package to github (or other repository) and then wait for the package to update using composer update.  For package development, composer has such feature as path repositories.  Let’s imagine we have a two folders on the same level:  my-app and  package.   my-app is an app — a test…

    Share this article