Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Setup and use parameters in PHPUnit data providers

I'm trying to write tests for a service which uses global parameters (from YML files).

I'm retrieving this parameters in the setUp() method, but when I try to use them in a @dataProvider, it throws an error.

class InterpreterServiceTest extends KernelTestCase
{
    private $container;
    private $service;
    private $citiesMap;

    public function setUp()
    {
        self::bootKernel();
        $this->container = self::$kernel->getContainer();
        $this->service = $this->container->get('geolocation.interpreter');
        $this->citiesMap = $this->container->getParameter("citiesmap");
        self::tearDown();
    }

    /**
     * @dataProvider locationsProvider
     */
    public function testCompanyCityFromCity($location, $expected)
    {
        $city = $this->service->getCompanyCityFromCity($location);
        $this->assertEquals($expected, $city);
    }

    public function locationsProvider()
    {
        $return = array();
        foreach ($this->citiesMap as $area) {
            $return[] = [
                $area['external_service_area'],
                $area['company_area']
            ];
        }
        return $return;
    }
}

Invalid argument supplied for foreach()

If I manually write the return of locationsProvider() it works

return [
    ["Barcelona", "Barcelona"],
    ["Madrid", "Madrid"],
    ["Cartagena", "Murcia"]
];

I also have checked the foreach in setUp() and it returns the proper expected array.


It seems the @dataProvider is executed before the setUp() method.

Is there a different way to do this?

like image 250
CarlosAS Avatar asked Jul 31 '17 08:07

CarlosAS


People also ask

What is the purpose of PHPUnit?

PHPUnit is a framework independent library for unit testing PHP. Unit testing is a method by which small units of code are tested against expected results. Traditional testing tests an app as a whole meaning that individual components rarely get tested alone.

What are PHPUnit fixtures?

One of the most time-consuming parts of writing tests is writing the code to set the world up in a known state and then return it to its original state when the test is complete. This known state is called the fixture of the test.

What is data provider PHP?

Data Providers allow us to define tests once and run them multiple times with different datasets. Using a data provider requires three steps: Define a public method that returns an array of datasets to be used. Annotate the data provider in the docblock of your test. Pass the dataset as an argument to the test method.

How do I run PHPUnit on Windows?

Open file Explorer and type "C:\windows\system32", then find cmd.exe and right click and select "Run as administrator". Start the Command Prompt as Administrator by clicking Start, All programs and Accessories, then right-click on Command Prompt link and selecting "Run as Administrator" from the context menu.


1 Answers

Afraid you have to get all your data (incl. service obj) inside the dataProvider method

TL&DR This should do it:

class InterpreterServiceTest extends KernelTestCase
{
    /**
     * @dataProvider locationsProvider
     */
    public function testCompanyCityFromCity($service, $location, $expected)
    {
        $city = $service->getCompanyCityFromCity($location);

        $this->assertEquals($expected, $city);
    }

    public function locationsProvider()
    {
        self::bootKernel();

        $container = self::$kernel->getContainer();
        $service = $this->container->get('geolocation.interpreter');
        $citiesMap = $this->container->getParameter("citiesmap");
        // self::tearDown(); - depends on what is in the tearDown

        $return = array();
        foreach ($citiesMap as $area) {
            $return[] = [
                $service,
                $area['external_service_area'],
                $area['company_area']
            ];
        }

        return $return;
    }
}

Why:

Both setUp and setUpBeforeClass methods are run inside the run method of the PHPUnit_Framework_TestSuite class. However, data from the dataProvider is calculated earlier as part of createTest function.

like image 195
BVengerov Avatar answered Sep 30 '22 08:09

BVengerov