2017 © Pedro Peláez
 

symfony-bundle test-double-bundle

Easily create test doubles using symfony DIC

image

docteurklein/test-double-bundle

Easily create test doubles using symfony DIC

  • Monday, February 29, 2016
  • by florian.klein@free.fr
  • Repository
  • 1 Watchers
  • 41 Stars
  • 32,711 Installations
  • PHP
  • 0 Dependents
  • 0 Suggesters
  • 5 Forks
  • 5 Open issues
  • 3 Versions
  • 17 % Grown

The README.md

TestDoubleBundle

What ?

A symfony bundle that eases creation of test doubles., (*1)

Using DIC tags, you can automatically replace a service with either a stub or a fake., (*2)

Why ?

To improve isolation of tests and increase the precision and variation of test fixtures., (*3)

Usually, our behat suite is using real data, coming from database fixtures.
This forces us to create gobal, universal, works-for-all fixtures., (*4)

A real database also implies to reset the state before each scenario.
This process is slow, and is just a workaround for having broken isolation., (*5)

An ideal test suite would run each scenario using only in-memory repositories.
Each scenario should define how the SUS behaves given a specific context.
Having a global implicit context (the database fixtures) makes it really hard to test different cases., (*6)

One solution is to replace your repositories with stubs.
Each scenario configures only the stubs required for it to work., (*7)

Note: Stubbed data is not resilient across processes, and thus doesn't fit for end-to-end testing like a typical mink+behat suite., (*8)

But now that repositories are doubled, how do you know if your real repositories still work?
Well, that's the role of infrastructure tests. Only those run against a real backend, be it a database for repositories, or a server for an http client., (*9)

To access the real services, just use <original-id>.real., (*10)

By doing that, you theoretically have a good coverage, isolation, speed
and you can better catch the origin of a regression., (*11)

All this while applying modelling by example., (*12)

How ?

install

composer require docteurklein/test-double-bundle --dev

register the bundle

``` php, (*13)

public function registerBundles()
{
    $bundles = [
        new \DocteurKlein\TestDoubleBundle,
        // …
    ];

    return $bundles;
}

> Note: You might want to add this bundle only in test env. ### integrate with behat This approach integrates very well with the [Symfony2Extension](https://github.com/Behat/Symfony2Extension/blob/master/doc/index.rst#injecting-services). You can then inject the service and/or the prophecy in your context class. You can also inject the container and access all the services at once. ## Examples > Note: The following examples use JmsDiExtraBundle to simplify code. ### Stubs Stubs are created using [prophecy](https://github.com/phpspec/prophecy). > Note: if you don't provide any tag attribute, then a stub is created. > if no class or interface is given to the `stub` attribute, then a stub for the service class will be created. > A stubbed class cannot be final. - First, define a stub DIC tag for the service ``` php /** * @Service("github_client") * @Tag("test_double", attributes={"stub"="GithubClient"}) */ final class GuzzleClient implements GithubClient { public function addIssue(Issue $issue) { // … } }
  • Automatically, the original github_client service is replaced with the github_client.stub service.

In order to control this stub, you have to use the github_client.prophecy service:, (*14)

``` php $issue = new Issue('test'); $container->get('github_client.prophecy')->addIssue($issue)->willReturn(true);, (*15)


### Fake > Note: fakes are really just DIC aliases. Imagine you have a service you want to double. - First, create this service and add a tag with the corresponding fake service: ``` php /** * @Service("github_client") * @Tag("test_double", attributes={"fake"="github_client.fake"}) */ final class GuzzleClient implements GithubClient { public function addIssue(Issue $issue) { // … } }
  • Then, create a fake implementation and register it with the fake id:

``` php /** * @Service("github_client.fake") */ final class FakeClient implements GithubClient { public function addIssue(Issue $issue) { // … } }, (*16)


### Behat > Note: We tagged `repo.invoices` and `http.client` as **stub**. ``` php class Domain implements Context { public function __construct($container) { $this->container = $container; } /** * @Given a building in "maintenance mode" */ public function aBuildingInMaintenanceMode() { $this->building = new Building('BUILDING1337'); $this->building->putInMaintenanceMode(); } /** * @When its last unpaid invoice is being paid */ public function itsLastUnpaidInvoiceIsBeingPaid() { $this->container ->get('repo.invoices.prophecy') ->findOneByReference('UNPAID04') ->willReturn(Invoice::ownedBy($this->building)) ; $pay = $this->container->get('app.task.invoice.pay'); $pay('UNPAID04'); } /** * @Then it should be removed from maintenance mode */ public function itShouldBeRemovedFromMaintenanceMode() { $this->container ->get('http.client.prophecy') ->removeFromMaintenanceMode('BUILDING1337') ->shouldHaveBeenCalled() ; $this->container->get('stub.prophet')->checkPredictions(); } }

The Versions

29/02 2016

dev-wip/doubler-class-patch

dev-wip/doubler-class-patch

Easily create test doubles using symfony DIC

  Sources   Download

MIT

The Requires

 

27/02 2016

dev-master

9999999-dev

Easily create test doubles using symfony DIC

  Sources   Download

MIT

The Requires

 

27/02 2016

1.0.0

1.0.0.0

Easily create test doubles using symfony DIC

  Sources   Download

MIT

The Requires