2017-04-05 19 views
0

如何在派發作業之後拋出異常的情況下測試作業參數。下面的測試返回綠色,但我沒有辦法測試工作參數。如何測試Laravel中的工作參數?

代碼:

<?php 

namespace Tests\Feature; 

use Illuminate\Bus\Queueable; 
use Illuminate\Contracts\Queue\ShouldQueue; 
use Illuminate\Foundation\Bus\Dispatchable; 
use Illuminate\Queue\InteractsWithQueue; 
use Illuminate\Queue\SerializesModels; 
use Tests\TestCase; 

class SomeJob implements ShouldQueue 
{ 
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; 
    public function handle() {} 
} 

class NothingTest extends TestCase 
{ 
    /** @test */ 
    public function dispatch_test() 
    { 
     $this->expectException(\Exception::class); 
     $this->expectsJobs(SomeJob::class); 

     // job dispatched and Exception thrown afterwards 
     dispatch(new SomeJob("argument to test")); 
     throw new \Exception(); 
    } 
} 

回答

1

我居然遇到了這個今天早些時候我自己。我所做的解決此問題的方法是使用withoutJobs()方法。 (內部expectsJobs()也會這樣調用。)然後,您可以對dispatchedJobs屬性進行斷言。

因爲你也是「期待」並在測試例外,你應該在回調中把這個包,並將其註冊在beforeApplicationDestroyed()

class SomeJob { 
    private $argument; 

    public function __construct($argument) 
    { 
     $this->argument = $argument; 
    } 
} 


class NothingTest extends TestCase 
{ 
    /** @test */ 
    public function dispatch_test() 
    { 
     $this->expectException(\Exception::class); 
     $this->beforeApplicationDestroyed(function() { 
      // This part depends on how you would like to design this. You could 
      // use public properties, add a getter method on your job or use 
      // something like reflection to compare the properties. 
      $dispatchedJob = $this->dispatchedJobs[0]; 
      $this->assertEquals(
       'argument to test', 
       $this->getValue($dispatchedJob, 'argument') 
      ); 
     }); 

     // job dispatched and Exception thrown afterwards 
     dispatch(new SomeJob("argument to test")); 
     throw new \Exception(); 
    } 

    protected function getValue($object, $name) 
    { 
     $ro = new \ReflectionObject($object); 
     $property = $ro->getProperty($name); 
     $property->setAccessible(true); 

     return $property->getValue($object); 
    } 
} 
+0

你已經提到反思 - 我試圖找到沒有辦法獲得傳遞參數的值。它實際上可能嗎? –

+0

我不認爲如果你不把它們分配給屬性,你實際上可以獲得通過參數。我已更新示例以顯示如何獲取私有屬性的值 –

+0

我已經找到了一種方法來僅使用IOC容器測試參數而沒有反射。看看下面。好點嗎? –

0

確定。可以像下面的代碼一樣測試。 測試看起來不錯,但你必須使用公共屬性並將所有參數分配給屬性。

<?php 

namespace Tests\Examples; 

use Illuminate\Bus\Queueable; 
use Illuminate\Contracts\Queue\ShouldQueue; 
use Illuminate\Foundation\Bus\Dispatchable; 
use Illuminate\Queue\InteractsWithQueue; 
use Illuminate\Queue\SerializesModels; 
use Tests\TestCase; 

class SomeJob implements ShouldQueue 
{ 
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; 

    public $arg1; 
    public $arg2; 

    public function __construct($arg1, $arg2) 
    { 
     $this->arg1 = $arg1; 
     $this->arg2 = $arg2; 
    } 
    public function handle() {} 
} 

class JobTest extends TestCase 
{ 
    /** @test */ 
    public function dispatch_test() 
    { 
     $this->expectException(\Exception::class); 
     $this->expectsJobs(SomeJob::class); 

     $this->testJobInstance(SomeJob::class, function($job){ 
      $this->assertEquals('arg1', $job->arg1); 
      $this->assertEquals('arg2', $job->arg2); 
     }); 

     // job dispatched and Exception thrown afterwards 
     dispatch(new SomeJob("arg1", "arg2")); 
     throw new \Exception(); 
    } 


    // will be pushed up to TestCase 
    protected function testJobInstance($class, callable $callback) 
    { 
     $this->beforeApplicationDestroyed(function() use($class, $callback) { 

      $job = collect($this->dispatchedJobs)->filter(function($job) use($class) { 
       return get_class($job) == $class; 
      })->first(); 

      $callback($job); 

     }); 
    } 
} 
0

好了,找到了更好的辦法...

我做了一個輔助函數派遣國際奧委會的工作 - 這讓很多更容易測試工作。

/** 
* @param string | object $job 
* @param array | null $args - associative array of arguments ['agr1' => 'value', 'arg2' => 2] 
* @return mixed 
*/ 
function dispatch_from_ioc($job, ? array $args) 
{ 
    if (is_string($job)) { 
     $job = app()->makeWith($job, $args); 
    } 

    return app(Dispatcher::class)->dispatch($job); 
} 

所以現在我可以測試工作的參數是這樣的:

/** @test */ 
public function test_jobs_arguments() 
{ 
    $this->app->bind(
     RealJob::class, 
     function($app, $args){ 

      // assertions against arguments 
      $this->assertEquals("argument", $args["arg"]); 
      $this->assertEquals([], $args["arg2"]); 

      return new FakeJob; 
     } 
    ); 

    // System under test 
    dispatch_from_ioc(RealJob::class, ["arg" => "argument", "arg2" => []]); 
} 

虛假招聘類

<?php 

namespace App\Jobs; 

use Illuminate\Bus\Queueable; 
use Illuminate\Queue\SerializesModels; 
use Illuminate\Queue\InteractsWithQueue; 
use Illuminate\Contracts\Queue\ShouldQueue; 
use Illuminate\Foundation\Bus\Dispatchable; 

class FakeJob extends Job 
{ 
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; 
    public function __construct() {} 
    public function handle() {} 
} 

是否有道理? :)