So I have an object which I am mocking and it has methods that are used for sending emails. I have gone from a static class over to a concrete class because I was having issues testing the static class with Mockery.
However I am now finding that when an eloquent model is saved it throws an event which fires off a listener. This listener is what is responsible for kicking off the call to the mock objects method.
I have found that when I do something like the following it works.
$model = factory(MyClass::class)->make();
$model->property = 'value';
$model->save()
$this->mailer->shouldHaveReceived('methodName')->with($arg1, $arg2, $arg3);
It will fail every time complaining that the method does not exist on the mock object, the worst part is if I go into my listener where the mock object method is called and I do something like this
echo '<pre>'.print_r(get_class_methods($this->mailer), true).'</pre>'; exit;
it shows that the method is in-fact in the array of methods returned from get_class_methods.
Now here is the kicker. Everything works perfectly and the test passes without any errors if I do the following:
$this->mailer->shouldReceive('methodName');
$model = factory(MyClass::class)->make();
$model->property = 'value';
$model->save()
Now I have been reading the Mockery Gotchas and it would appear that if my class was calling a method that truly didn't exist on the object via ___call
then this error would be expected.
However my mailer class is NOT extending any other class that would have a __call
method nor does it have that method defined on the class.
However as you may or may not know Eloquent Models do in-fact use the magic ___call
method. However I am NOT mocking the model with Mockery, I am using factory models in Laravel but I am also not checking the model object for the method call, I am checking my concrete mailer class for the method call.
Anyone know why I might be getting this behavior from Mockery?
I am creating my mock object in Laravel 5.2 with the following code
public function mock($class)
{
$mock = Mockery::mock($class);
$this->app->instance($class, $mock);
return $mock;
}
$this->mailer = $this->mock('Namespace\Classname');