SkillAgentSearch skills...

ICBaseTestBundle

Provides lower level support for unit and functional tests in Symfony2

Install / Use

/learn @instaclick/ICBaseTestBundle
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

InstaClick Base Test Bundle

IMPORTANT NOTICE: This bundle is still under development. Any changes will be done without prior notice to consumers of this package. Of course this code will become stable at a certain point, but for now, use at your own risk.

Introduction

This bundle provides lower level support for unit and functional tests on Symfony2. Through the concept of helpers and loaders, this bundle supports individual support for test types, such as Command, Controller, Service, Validator, etc.

This bundle requires that you are using, at least, Symfony 2.1.

Installation

Installing this bundle can be done through these simple steps:

  1. Add this bundle to your project as a composer dependency:
    // composer.json
    {
        // ...
        require-dev: {
            // ...
            "instaclick/base-test-bundle": "dev-master"
        }
    }
  1. Add this bundle in your application kernel:
    // application/ApplicationKernel.php
    public function registerBundles()
    {
        // ...
        if (in_array($this->getEnvironment(), array('test'))) {
            $bundles[] = new IC\Bundle\Base\TestBundle\ICBaseTestBundle();
        }

        return $bundles;
    }
  1. Double check if your session name is configured correctly:
# application/config/config_test.yml
    framework:
        test: ~
        session:
            name: "myapp"

Unit Testing

By default, Symfony2 does not provide a native customized support for unit test creation. To mitigate this problem, this bundle contains a wide set of basic unit test abstraction to help you with this job.

Protected/Private

There may be times where you want to directly test a protected/private method or access a non-public property (and the class lacks a getter or setter). For example, the call chain from the closest public method is sufficiently long to make testing an arduous task.

To overcome this obstacle, TestCase provides some methods to assist you.

Let's say this is your subject under test:

class Foo
{
    protected $bar;

    private function getBar()
    {
        return $this->bar;
    }
}

Here is an example:

use IC\Bundle\Base\TestBundle\Test\TestCase;

class ICFooBarBundleTest extends TestCase
{
    public function testGetBar()
    {
        $subject = new Foo;
        $expected = 'Hello';

        $this->setPropertyOnObject($subject, 'bar', $expected);

        $method = $this->makeCallable($subject, 'getBar');

        $this->assertEquals($expected, $method->invoke($subject));
    }
}

Bundle testing

Most people do not even think about testing a bundle initialization. This is a bad concept, because every line of code deserves to be tested, even though you may not have manually created a class.

Bundle classes are known to be the place to register your CompilerPass instances. No matter if you have a CompilerPass or not, it is a good practice to create a default test for your Bundle class. Here is an example on how to achieve it:

use IC\Bundle\Base\TestBundle\Test\BundleTestCase;
use IC\Bundle\Base\MailBundle\ICBaseMailBundle;

class ICBaseMailBundleTest extends BundleTestCase
{
    public function testBuild()
    {
        $bundle = new ICBaseMailBundle();

        $bundle->build($this->container);

        // Add your tests here
    }
}

Dependency Injection

Configuration testing

Just like Bundle classes, Configuration classes are very easy to overlook when testing. Testing this specific test is a good approach because it validates your line of thought with Bundle configuration normalization of parameters or even configuration default values. ICBaseTestBundle already provides a small class that can help you with this task.

use IC\Bundle\Base\TestBundle\Test\DependencyInjection\ConfigurationTestCase;
use IC\Bundle\Base\MailBundle\DependencyInjection\Configuration;

class ConfigurationTest extends ConfigurationTestCase
{
    public function testDefaults()
    {
        $configuration = $this->processConfiguration(new Configuration(), array());

        $this->assertEquals('INBOX', $configuration['mail_bounce']['mailbox']);
    }

    // ...
}

Extension testing

Testing the DependencyInjection Extension helps you to validate your service definitions and container configuration. Helpful methods available to you:

  • assertAlias($expected, $key)
  • assertParameter($expected, $key)
  • assertHasDefinition($id)
  • assertDICConstructorArguments(Definition $definition, array $arguments)
  • assertDICDefinitionClass(Definition $definition, $expectedClass)
  • assertDICDefinitionMethodCallAt($position, Definition $definition, $methodName, array $params = null)
use IC\Bundle\Base\TestBundle\Test\DependencyInjection\ExtensionTestCase;
use IC\Bundle\Base\MailBundle\DependencyInjection\ICBaseMailExtension;

class ICBaseMailExtensionTest extends ExtensionTestCase
{
    /**
     * @expectedException \Symfony\Component\Config\Definition\Exception\InvalidConfigurationException
     */
    public function testInvalidConfiguration()
    {
        $extension     = new ICBaseMailExtension();
        $configuration = array();

        $this->load($extension, $configuration);
    }

    public function testValidConfiguration()
    {
        $this->createFullConfiguration();

        $this->assertParameter('John Smith', 'ic_base_mail.composer.default_sender.name');

        $this->assertDICConstructorArguments(
            $this->container->getDefinition('ic_base_mail.service.composer'),
            array()
        );
        $this->assertDICConstructorArguments(
            $this->container->getDefinition('ic_base_mail.service.sender'),
            array()
        );
        $this->assertDICConstructorArguments(
            $this->container->getDefinition('ic_base_mail.service.bounce_mail'),
            array()
        );
    }

    // ...
}

Validator testing

Validators are a key part of the system, because it helps you verify your business rules are being respected. Testing them becomes even more crucial. Constraints can generate violations at different locations. In order to help you verify it assigns it at the correct place, ValidatorTestCase provides you a set of methods:

  • assertValid(ConstraintValidator $validator, Constraint $constraint, $value)
  • assertInvalid(ConstraintValidator $validator, Constraint $constraint, $value, $message, array $parameters = array())
  • assertInvalidAtPath(ConstraintValidator $validator, Constraint $constraint, $value, $type, $message, array $parameters = array())
  • assertInvalidAtSubPath(ConstraintValidator $validator, Constraint $constraint, $value, $type, $message, array $parameters = array())
use MyBundle\Validator\Constraints;
use IC\Bundle\Base\TestBundle\Test\Validator\ValidatorTestCase;

class BannedEmailValidatorTest extends ValidatorTestCase
{
    public function testValid()
    {
        $validator  = new Constraints\BannedEmailValidator();
        $constraint = new Constraints\BannedEmail();
        $value      = 'email@domain.com';

        $this->assertValid($validator, $constraint, $value);
    }

    public function testInvalid()
    {
        $validator  = new Constraints\BannedEmailValidator();
        $constraint = new Constraints\BannedEmail();
        $value      = 'domain.com';
        $message    = 'Please provide a valid email.';
        $parameters = array();

        $this->assertInvalid($validator, $constraint, $value, $message, $parameters);
    }
}

Creating your first functional test

Just like a Symfony2 test, implementing a functional test is easy:

use IC\Bundle\Base\TestBundle\Test\Functional\WebTestCase;

class MyFunctionalTest extends WebTestCase
{
    public function testSomething()
    {
        // Normal test here. You can benefit from an already initialized
        // Symfony2 Client by using directly $this->getClient()
    }
}

Functional tests that requires Database to be initialized

When building your functional tests, it is recurrent that you want your test Database to be created and populated with initial information. This bundle comes with native support for Doctrine Data Fixtures, which allows you to load your database information before your test is actually executed.

To enable your schema to be initialized and also load the initial Database information, just implement the protected static method getFixtureList:

/**
 * {@inheritdoc}
 */
protected static function getFixtureList()
{
    return array(
        'Me\MyBundle\DataFixtures\ORM\LoadData'
    );
}

If you don't need any fixtures to be loaded before your test, but still want your empty Database schema to be loaded, you can tell the TestCase to still force the schema to be loaded by changing the configuration property flag:

protected $forceSchemaLoad = true;

Overriding the default client instance

Some applications require more granular control than what Symfony2 Client can do. This bundle allows you to change the default client initialization, just like you normally do with your Symfony2 WebTestCase, by overriding the static method createClient.

Changing Client environment

This bundle allows you to easily change the environment the Client gets initialized. To change the default environment (default: "test"), just redefine the constant ENVIRONMENT:

const ENVIRONMENT = "default";

Changing default Object Manager name

When using Databases, you may want to change the default ObjectManager your test should run against. Just like Client's environment, changing the default ObjectManager only requires you to redefine the constant MANAGER_NAME:

const MANAGER_NAME = "stats";

Server authentication

Whenever your application uses HTTP authentication, your test should still have an ability to test secured pages. With simplicity in mind, Client can be initialized in an

Related Skills

View on GitHub
GitHub Stars95
CategoryCustomer
Updated4mo ago
Forks21

Languages

PHP

Security Score

77/100

Audited on Nov 2, 2025

No findings