如何在Laravel中测试工作参数?

时间:2017-04-05 14:27:36

标签: laravel laravel-5 tdd laravel-5.4

如果在调度作业后抛出异常,如何测试作业参数。下面的测试返回绿色,但我发现无法测试作业参数。

代码:

<?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();
    }
}

3 个答案:

答案 0 :(得分: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);
    }
}

答案 1 :(得分: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);

        });
    }
}

答案 2 :(得分:0)

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

我已经帮助从IOC派遣工作 - 这使得测试工作变得更加容易。

/**
 * @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() {}
}

有意义吗? :)