PHPUnit, Using class consts to change State
Asked Answered
M

2

3

I'm learning Zend and also PHPUnit.

Here is what I have below


public function changeToIllegalState()
{
    return array(
        array( Application_Model_SomeModel::FAIL ),
        array( Application_Model_SomeModel::SUCCESS )
    );
}

/**
 * @dataProvider changeToIllegalState
 * @expectedException IllegalStateChangeException
 */

public function testIllegalStateChangeGeneratesException( $state )
{
    $mapper = new Application_Model_Mapper_SomeModel();
    $model = new Application_Model_SomeModel();

    $model->changeState( $state );

    $mapper->save( $model );

}

So as you can see here, the data provider provides some constants that represent different states from the model.

PHPUnit says that it can't find the Model class in the dataprovider method. However, if I try to use the constants within the test methods, it all works and there are no problems. I'm using the Zend autoloader to load my classes and it has all been dandy up till now. I know that I could just put in the values for the constants themselves, but I don't know why I'm getting this error.

I can only assume that the dataprovider methods are called before the setup method is called because I do all the autoloading business in the setup method.

EDIT :

I have also tried the following but it still won't work with the class consts.



protected $_FAIL;
protected $_model;

public function setUp()
{
    parent::setUp();
    $this->_model = new Application_Model_SomeModel();
    $this->_FAIL = Application_Model_SomeModel::FAIL;
}

Now, when I try to use $_FAIL in the provider method I get a NULL value instead of the 'fail' string that I'm expecting. This is really weird.

Megaphone answered 6/4, 2011 at 5:26 Comment(2)
what does $class = new ReflectionClass("Application_Model_SomeModel"); var_dump(class->getConstants()) and var_dump(FAIL); (without quotes) output when you write it in the setUp() ?Valdes
If I put what you suggested into the setUp() method, everything works as expected. Meaning that all the constants and their values of the class are printed AND the class variable FAIL is the correct string value. However, if I put var_dump( $this->_FAIL ) in the dataprovider method, right before I return the array, then a NULL value is printed for $this->_FAIL.Megaphone
E
4

PHPUnit instantiates all of test cases that will be run before running any tests.

  • One per test method without a data provider.
  • One per data provider method.
  • One per parameter array returned from each data provider, so a provider that returns an array of four arrays gets four test case instances.

Assuming you're setting up the autoloader in your bootstrap.php, it should load the class containing those constants. However, I would try a test to see:

public function changeToIllegalState()
{
    require_once 'Zend/Loader/Autoloader';
    Zend_Loader_Autoloader::getInstance();

    return array(
        array( Application_Model_SomeModel::FAIL ),
        array( Application_Model_SomeModel::SUCCESS )
    );
}

Or is Zend Framework adding the models' directory to the include path in one of the test case's setUp() method instead?

Erzurum answered 6/4, 2011 at 7:5 Comment(4)
Yes, I'm initiating the autoloader in the bootstrap and during the setUp method I'm instantiating a Zend_Application object that adds my models to the include path.Megaphone
I tried what you suggested, and but put down require_once 'Zend/Loader/Autoloader.PHP' instead. It still didn't work, however, and I got the same error message from before.Megaphone
You were right but I didn't really understand your answerv When you said "test case" I thought that you meant the class that the test methods are in, not the test methods themselves. I did instantiate the autoloader in the bootstrap but I had to instantiate the Zend_Application in the bootstrap as well to enable the autoloading of mf models as well since the Zend_Application adds them to the autoloader during construction.Megaphone
@Jerry - By test case I did mean the class that contains the test methods. Their setUp() methods are not called until after the data provider methods have been called. Thus, your solution of instantiating the application in bootstrap.php is correct as now it adds the models' directory to the include path before calling the data provider methods.Erzurum
M
3

I figured out what is going on, finally.

PHPUnit will call all the dataprovider methods of a class before it calls any of the setup methods, this includes the static method setUpBeforeClass.

I put in a bunch of echo statements in the data provider methods and setUp methods to confirm this. All the provider method echos always printed before setup method echos.

In addition, the echos of provider methods were only echoed when the methods were declared as data providers with the dataprovider annotation. That is to say, any methods not declared as dataprovider methods with the annotation are not called at all.

My initial assumption about PHPUnit calling the provider methods before my setUp method was right.

To fix this, I have to instantiate my Zend_Application object in the bootstrap file instead of in the setUp method. I didn't want to do this because I didn't need the Zend_Application object for all the test cases but I think that this is what I'll end up doing since it'll make my life a little easier.

@David Harkness you were right about setting up the autoloader in the bootstrap in this case but I also needed to setup the application autoloading (by making the Zend_Application object), not just the Zend library autoloading.

Megaphone answered 6/4, 2011 at 19:8 Comment(4)
Yes, this was what I meant by the last sentence of my answer, though I admit to being a tad terse. ;)Erzurum
@David Harkness - Thanks for the help though David, I should have read your answer more carefully too. It woulda saved me some time.Megaphone
I've never seen terseness measured in tads, but I suppose it's possible.Officeholder
@Steve, a spoon of sugar, a tad of terse :-)Megaphone

© 2022 - 2024 — McMap. All rights reserved.