5

I'm writing tests for a model which fires an event when one of its properties is changed. Unfortunately, I can't figure out the best way to test this. The model code is:

class Foo extends Eloquent {
   public function setNameAttribute($value) {
        $this->attributes['name'] = $value;
        if($this->exists && ($this->original['name'] != $value)) {
            Event::fire('foo.NameChange', array($this));
        }
    }
}

My initial test for the event fire:

$bar = Foo::first();
Event::shouldReceive('fire')->once()->with('foo.NameChange', array($bar));
$bar->name = 'test';

The problem is, the above tests still pass if:

  • no event occurred at all
  • I'm changing the model's name for a second time (which, should fire the event for a second time, right?)

How can i make my tests pass only if one foo.NameChange event occurred? All other senario's should fail my test.

nstapelbroek
  • 75
  • 1
  • 7
  • Your test should fail if no `event` occured at all - as you've mocked it and said it should be fired `once`? – Laurence Mar 19 '15 at 16:55
  • Did you call `Mockery::close()`?, also see my explanation on an [old SO question](http://stackoverflow.com/questions/16035549/mockery-shouldreceive-once-doesnt-seem-to-work/16308814#16308814) – Bram Gerritsen Mar 19 '15 at 20:44
  • Thanks a lot @BramGerritsen! closing the test with an `Mockery::close()` statement did fix it! Could you be so kind to convert your comment to an answer? Also i wonder why this is not mentioned in the official documentation of [Laravel](http://laravel.com/docs/4.2/testing#mocking-facades). – nstapelbroek Mar 19 '15 at 21:05
  • 1
    I don't use Laravel myself, but I think it should definitely be mentioned in the manual. Maybe you could notify the framework authors about it. Nothing is so frustrating when learning a framework when you have to deal with non working example code in official tutorials. – Bram Gerritsen Mar 19 '15 at 21:52
  • @nstapelbroek Do mind that you don't *have* to call `Mockery::close()` in each test, *if* you set it up for the entire suite (see the manual referenced by Bram). – Berry Langerak Dec 17 '15 at 14:05

1 Answers1

2

You have to call Mockery::close() in your tearDown() method. See the Mockery docs on PHPUnit integration.

Bram Gerritsen
  • 7,178
  • 4
  • 35
  • 45