0
votes

In a certain observer class, I've got this code

//Just for context
public function updated () {
    Artisan::queue('campaign:resume', ['campaignId' => $campaign->id]);
}

The purpose is to test that the command is indeed queued when the conditions met. I've tried several approaches but as far as I can tell, Queue::fake() doesn't affect the queue method and can't seem to find a way to use Bus::fake to assert this queued command.

This is what I've tested and commented is what I've tried. Again, the content of the Observer is simplified as it doesn't matter.

public function testSomeClassShouldQueueACommand() {
        //Arrange
        //Queue::fake();
        //$fakeBus = Bus::fake();
        $campaignObserver = new CampaignObserver();
        //$this->app->instance(\Illuminate\Foundation\Bus\PendingDispatch::class, $fakeBus);
        //Act
        $campaignObserver->updated();
        //Assert
        //Bus::assertDispatched('campaign:resume');
        //Queue::assertPushed('campaign:resume');
        //Artisan::shouldReceive('queue')->with('campaign:resume');
    }

I've seen posts where some say: Just pass it to a job or an event and use Queue::fake/Event::fake. It's contents aren't something that should be in a Job nor an Event. It doesn't make sense to create a class to handle "queue" of a command if the Artisan can handle queues itself.

Any ideas on how to complete this unit test?

1

1 Answers

1
votes

First, I assume method you call us updated - in question you showed implementation of update method but you called updated method instead.

Second, I've tested it in Laravel 8 , but should work same in Laravel 6.

I think there is no way to test it using Laravel built-in fakes.

Let's assume, command for campaign:resume is in App\Console\Commands\TestArtisan class. Then you should be able to test like like so:


$mock = Mockery::mock(\App\Console\Commands\TestArtisan::class . '[handle]')->makePartial();
$this->instance(\App\Console\Commands\TestArtisan::class, $mock);

$mock->shouldReceive('handle')->once()->withNoArgs();

$campaignObserver = new CampaignObserver();

$campaignObserver->updated();

$this->assertSame([
    'command' => 'campaign:resume',
    'campaignId' => 'HERE_YOU_SHOULD_PUT_SOME_CAMPAIGN_ID',
    0 => 'campaign:resume',
], $mock->arguments());

So you create partial mock of command and make sure handle method was executed. Finally you can run some additional assertions, like for example comparing data in arguments() or anything else you need.