Lumen-framework: $this->expectsJobs not working

Created on 23 May 2016  Â·  20Comments  Â·  Source: laravel/lumen-framework

Hi,

I've using this method when testing my previous Laravel projects. I have now a job-heavy Lumen app on which I would like to do the same. But for some reason I cannot get this to work. I then pulled out an fresh Lumen 5.2.6 app and did the following changes to make the most simplistic working example. I assume this should work.

routes.php

<?php

use App\Jobs\ExampleJob;

$app->get('/', function () use ($app) {
    dispatch(new ExampleJob);
});

ExampleTest.php

<?php

class ExampleTest extends TestCase
{
    public function testExample()
    {
        $this->expectsJobs('App\Jobs\ExampleJob');

        $this->get('/');
    }
}

Running phpunit:

vagrant@homestead:~/Code/lumen-test$ phpunit
PHPUnit 4.8.26 by Sebastian Bergmann and contributors.

E

Time: 3.54 seconds, Memory: 6.00MB

There was 1 error:

1) ExampleTest::testExample
Mockery\Exception\InvalidCountException: Method dispatch(object(Mockery\Matcher\Type)) from Mockery_0_Illuminate_Bus_Dispatcher should be called
 at least 1 times but called 0 times.

/home/vagrant/Code/lumen-test/vendor/mockery/mockery/library/Mockery/CountValidator/AtLeast.php:48
/home/vagrant/Code/lumen-test/vendor/mockery/mockery/library/Mockery/Expectation.php:297
/home/vagrant/Code/lumen-test/vendor/mockery/mockery/library/Mockery/ExpectationDirector.php:120
/home/vagrant/Code/lumen-test/vendor/mockery/mockery/library/Mockery/Container.php:297
/home/vagrant/Code/lumen-test/vendor/mockery/mockery/library/Mockery/Container.php:282
/home/vagrant/Code/lumen-test/vendor/mockery/mockery/library/Mockery.php:142
/home/vagrant/Code/lumen-test/vendor/laravel/lumen-framework/src/Testing/TestCase.php:107

FAILURES!
Tests: 1, Assertions: 0, Errors: 1.

bug

Most helpful comment

I'm pretty sure I figured out what is happening.

  1. The expectsJobs method replaces the container binding with the mock.
  2. When the dispatch helper function calls make on the app, the make function calls registerBusBindings, which overwrites the mock binding with the real binding.
  3. Since the mock binding is overwritten, the app gets the real thing and the method is never called on the mock.

I added a failing test here, that shows how the container overwrites bindings. This will happen with any bindings listed in the availableBindings property of the application.

A hacky workaround is to resolve the object once out of the container before trying to register your binding.

All 20 comments

What version of mockery please. Could you run composer show -i.

Seems like mockery/mockery version is 0.9.5. This comes from the version constraint ~9.0 in the Lumen composer.json.

Does it work if you hard code it to 0.9.4 please?

I tried from 0.9.4 to 0.9.0 and none of these worked. So it's leaning towards in issue with Lumen instead of mockery breaking BC on a patch version update?

same problem, its not working for me as well. using Mockery 0.9.4 and using dispatch() function doesn't pass the test

I'm pretty sure I figured out what is happening.

  1. The expectsJobs method replaces the container binding with the mock.
  2. When the dispatch helper function calls make on the app, the make function calls registerBusBindings, which overwrites the mock binding with the real binding.
  3. Since the mock binding is overwritten, the app gets the real thing and the method is never called on the mock.

I added a failing test here, that shows how the container overwrites bindings. This will happen with any bindings listed in the availableBindings property of the application.

A hacky workaround is to resolve the object once out of the container before trying to register your binding.

Has anyone come up with a solution for this? I'm a little confused as to what this comment means:

A hacky workaround is to resolve the object once out of the container before trying to register your binding.

@feeekkk you need to do something like this:

// Resolve the dispatcher even though we aren't using it.
app('Illuminate\Contracts\Bus\Dispatcher');

// Now it will work correctly
$this->expectsJobs($args);
On Jul 2, 2016 8:25 AM, "feeekkk" [email protected] wrote:

Has anyone come up with a solution for this? I'm a little confused as to
what this comment means:

A hacky workaround is to resolve the object once out of the container
before trying to register your binding.

—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
https://github.com/laravel/lumen-framework/issues/416#issuecomment-230099293,
or mute the thread
https://github.com/notifications/unsubscribe/AJAMx0iUEXgJUjQO2n9IdeZCt_Fbh8qRks5qRliegaJpZM4IkT0s
.

Hi there, this is solved? I'm facing the same problem with a simple test...

@pedroplanel move the call to $this->expectsJob(JobName); able the rest of your test logic

I have the same problem, am using lumen 5.5

This seems to be fixed in 5.7. Let me know if you're still experiencing this.

@driesvints the test case I added is still failing in 5.7. I don't believe this is fixed.

Simple example with psysh:

>>> $mock = Mockery::mock('Illuminate\Bus\Dispatcher');
=> Mockery_0_Illuminate_Bus_Dispatcher {#238}
>>> $app->instance('Illuminate\Contracts\Bus\Dispatcher', $mock);
=> Mockery_0_Illuminate_Bus_Dispatcher {#238}
>>> $app['Illuminate\Contracts\Bus\Dispatcher']
=> Illuminate\Bus\Dispatcher {#200}

Okay, I'll have another look at a later time. Thanks for reporting.

I can't seem to reproduce this anymore. the ExpectsJobs method is working fine for me.

Oh, it looks like expectsJobs specifically was fixed by 16a452a, but the underlying problem of container bindings being overwritten still exists. I can open a more specific issue for that.

With me, It's working with dispatch( ) but not working with event( )

@mostafaabdelbaset until this is fixed you can use the same workaround from 16a452a. This should work:

unset($this->app->availableBindings['events']);
unset($this->app->availableBindings['Illuminate\Contracts\Events\Dispatcher']);
$this->expectsEvents('SomeEvent');

This should work correctly now for expectsJobs, expectsEvents, or any other use case that requires overwriting an available binding.

Thanks @yuloh!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

patrikengborg picture patrikengborg  Â·  3Comments

cvinothkumar picture cvinothkumar  Â·  3Comments

dunice picture dunice  Â·  3Comments

gfazioli picture gfazioli  Â·  5Comments

timrogers picture timrogers  Â·  3Comments