Phpunit: Constructor in subclass of PHPUnit_Framework_TestCase causes @dataProvider to break

Created on 9 Aug 2012  ·  4Comments  ·  Source: sebastianbergmann/phpunit

Having a constructor in your test causes the dataProvider annotation to break with an error about missing arguments:

PHPUnit 3.6.12 by Sebastian Bergmann.

...E

Time: 0 seconds, Memory: 3.25Mb

There was 1 error:

1) Test::testTheProvider
Missing argument 1 for Test::testTheProvider()

/home/nick/development/PHP-1.php:43

FAILURES!
Tests: 4, Assertions: 5, Errors: 1.

Removing the constructor causes the testTheProvider to work again, and does not seem to break @depends annotations.

<?php
class Test extends PHPUnit_Framework_TestCase {

    public function __construct() {
        parent::__construct();
    }

    public function testEmpty() {
        $stack = array();
        $this->assertEmpty($stack);

        return $stack;
    }

    /**
     * @depends testEmpty
     */
    public function testPush(array $stack) {
        array_push($stack, 'foo');
        $this->assertEquals('foo', $stack[count($stack)-1]);
        $this->assertNotEmpty($stack);

        return $stack;
    }

    /**
     * @depends testPush
     */
    public function testPop(array $stack) {
        $this->assertEquals('foo', array_pop($stack));
        $this->assertEmpty($stack);
    }

    public function theProvider() {
        return array(
            array(true, false)
        );
    }

    /**
     * @dataProvider theProvider
     */
    public function testTheProvider($var1, $var2) {
        //$var1 = true;
        //$var2 = false;

        $this->assertNotEquals($var1, $var2);
    }

}
?>

Most helpful comment

I have solved the problem like this:

class Test extends PHPUnit_Framework_TestCase {
public function __construct($name = NULL, array $data = array(), $dataName = '') {
parent::__construct($name, $data, $dataName);
}
}

All 4 comments

Expected behaviour. If you override PHPUnit_Framework_TestCase::__construct() (which you should not) your implementation must accept all arguments of the original implementation and pass them on to parent::__construct().

Thank you for the clarification. However, the constructor in PHPUnit_Framework_TestCase provides default values for its arguments and they are defined the same anyway. Calling it should make no difference unless you specifically want to change something.

Moreover this isn't mentioned in the docs (http://www.phpunit.de/manual/current/en/extending-phpunit.html#extending-phpunit.PHPUnit_Framework_TestCase) and the DBUnit BankAccount sample even does this (https://github.com/sebastianbergmann/dbunit/blob/master/Samples/BankAccountDB/BankAccountDBTest.php#L60).

I wouldn't say it was expected behaviour if some annotations work and some do not just because of this.

I have solved the problem like this:

class Test extends PHPUnit_Framework_TestCase {
public function __construct($name = NULL, array $data = array(), $dataName = '') {
parent::__construct($name, $data, $dataName);
}
}

Hi,
I was lucky to find this answer, saved lot of time. Ty, @foued611

My case is like this and it fails.

# my base test class
use PHPUnit_Framework_TestCase;

class mytest extends PHPUnit_Framework_TestCase {
   public function __construct() {
     # do some common stuff to my tests...
  }
}


class IntegrationTest extends mytest {
  public function __construct() {
     parent::__construct();
  }
   /**
    * @dataProvider additionProvider
    */
    public function testAdd($a, $b, $expected)
    {
        $this->assertEquals($expected, $a + $b);
    }

    public function additionProvider()
    {
        return [
            'adding zeros'  => [0, 0, 0],
            'zero plus one' => [0, 1, 1],
            'one plus zero' => [1, 0, 1],
            'one plus one'  => [1, 1, 3]
        ];
    }

}

fixed and working version looks like this

# my base test class
use PHPUnit_Framework_TestCase;

class mytest extends PHPUnit_Framework_TestCase {
   public function __construct() {
     # do some common stuff to my tests...
    parent::__construct(...func_get_args());
  }
}


class IntegrationTest extends mytest {
  public function __construct($name = NULL, array $data = array(), $dataName = '') {
    parent::__construct(...func_get_args());
  }
   /**
    * @dataProvider additionProvider
    */
    public function testAdd($a, $b, $expected)
    {
        $this->assertEquals($expected, $a + $b);
    }

    public function additionProvider()
    {
        return [
            'adding zeros'  => [0, 0, 0],
            'zero plus one' => [0, 1, 1],
            'one plus zero' => [1, 0, 1],
            'one plus one'  => [1, 1, 3]
        ];
    }

}

Current PHPUnit documentation does not warn in any ways that do not add custom __constructor() for your tests classes which are using dataProvider. That information could be added in to current Data Providers documentation, at least it would give you a hint why your implementation is not working even if you copy-pasted the example dataProvider code.
And if you need to use custom __constructor add some guide how it can be made so that it works.

Ping because closed @sebastianbergmann

Was this page helpful?
0 / 5 - 0 ratings

Related issues

dkarlovi picture dkarlovi  ·  3Comments

AnmSaiful picture AnmSaiful  ·  4Comments

keradus picture keradus  ·  4Comments

TiMESPLiNTER picture TiMESPLiNTER  ·  3Comments

joubertredrat picture joubertredrat  ·  4Comments