Codeception / Specify

BDD style code blocks for PHPUnit / Codeception
MIT License
156 stars 22 forks source link

Specify does not isolate mock counters #23

Closed terrabruder closed 4 years ago

terrabruder commented 8 years ago

In general, the specify isolation is great. Unfortunately, the use of mock invocation counters limits the usefulness of specify.

(Test style sacrificed for clarity here)

Given a test of class 'BaseModel'

class BaseModelClass
{

    public function save($data = array(), $useValidation = true){
           if($useValidation){
                $this->validate($data);
           }

          //some save logic
     }

     public function validate(){
         // does some validation logic
     }

}

And a test class using specify

class BaseModelClassTest extends \Codeception\TestCase\Test
{

    use \Codeception\Specify;

    public function TestSaveMethod(){

        $data = array('key'=>'value');

        $this->specify('Should never call validate unless requested', function() use($data){

             $Model = Stub::makeEmptyExcept('BaseModel', 'save', array(
                      'validate'=>Stub::never();
             ));

             $result = $Model->save($data, false);

        });

        $this->specify('Should call validate once when requested', function() use($data){

             $Model = Stub::makeEmptyExcept('BaseModel', 'save', array(
                      'validate'=>Stub::once();
            ));

             $result = $Model->save($data, true);

        });

    }
}

This test will fail on the stub counter for validate.

ghost commented 4 years ago

Hi, i was trying to replicate this bug using PHP 7.1, PHPUnit 7 y Codeception/Stub 3.7. The code today would look like this:

    public function testSaveMethod() {

        $data = ['key' => 'value'];

        $this->specify('Should never call validate unless requested', function() use($data){
            $model = Stub::makeEmptyExcept(BaseModelClass::class, 'validate',[
                'save'=> Stub\Expected::once()
            ], $this);
            $result = $model->save($data, false);
        });
        $this->specify('Should call validate once when requested', function() use($data){
            $model = Stub::makeEmptyExcept(BaseModelClass::class, 'validate', [
                'save'=> Stub\Expected::never()
            ], $this);
        });
    }

and it works as expected. Even reversing the order, ('never' first, 'once' later), the tests generate the expected failure for the expected reason.


1) testSaveMethod | Should never call validate unless requested
Codeception\BaseModelClass::save(Array (...), false) was not expected to be called.

2) SpecifyTest::testSaveMethod
Expectation failed for method name is "save" when invoked 0 time(s).
Method was expected to be called 0 times, actually called 1 times.

Although two failures are generated, both are related to the first Specify execution. So... @DavertMik I think this can be closed. It can be reopened if it can be replicated in current release.