【问题标题】:Job incorrectly shows as dispatched during testing作业在测试期间错误地显示为已调度
【发布时间】:2021-08-25 18:09:35
【问题描述】:

我有以下测试用例:

protected function setUp(): void
{
    parent::setUp();
    Queue::fake();
}

public function testUpdate(): void
{
    $this->updateModel(["foo" => 123]);
    $this->assertDatabaseHas("models", ["foo" => 123]);
}

public function testQueueJob(): void
{
    $this->updateModel(["bar" => 456]);
    $this->assertDatabaseHas("models", ["bar" => 456]);
    $this->assertPushed(MyJob::class);
}

public function testDontQueueJob(): void
{
    $this->updateModel(["baz" => 789]);
    $this->assertDatabaseHas("models", ["baz" => 789]);
    $this->assertNotPushed(MyJob::class);
}

updateModel 只是向控制器推送一个发布请求。请求由这个方法处理:

public method update(Request $request, Model $model): JsonResponse
{
    $model->update($request->all());
    $model->save();
    if ($this->wasChanged("bar")) {
        MyJob::dispatch($model);
    }
    return response()->json($model);
}

很明显,我正在测试的是作业不会被推送到队列中。但是,我的最终测试失败了:

  The unexpected [App\Jobs\MyJob] job was pushed.
  Failed asserting that actual size 1 matches expected size 0.

我已通过dump() 声明确认在第三次测试期间该作业没有被推送。通过交换第二个和第三个测试,测试套件成功通过,表明在第二个测试中推入队列的作业已经持续到第三个测试。

我正在使用database 队列驱动程序(QUEUE_CONNECTION=database 中的.env.testing)并且RefreshDatabase 特征被导入到我的测试类中。这应该会在测试之间擦除数据库,但似乎不是。

当我尝试手动清除队列时,我得到:

Call to undefined method Illuminate\Support\Testing\Fakes\QueueFake::clear()

setUp 方法中是否有清除队列的方法?我应该以不同的方式处理这个问题吗?

【问题讨论】:

  • 根据测试的数量,它可能不实用,但是从 setUp 函数中删除 Queue::fake(); 并将其放入每个测试中应该可以解决这个问题
  • 刚刚试了一下,添加到所有单独的测试方法中。还是同样的失败。

标签: php laravel testing phpunit laravel-jobs


【解决方案1】:

我认为你应该使用faker

public function testDontQueueJob(): void
{
    $newNumber = $this->faker->numberBetween(100,999);
    $this->updateModel(["baz" => $newNumber]);
    $this->assertDatabaseHas("models", ["baz" => $newNumber]);
    $this->assertNotPushed(MyJob::class);
}

确保此条件有效

if ($this->wasChanged("bar")) {
    MyJob::dispatch($model);
}

测试顺序不应影响结果

我还注意到,您在测试中使用键“baz”,在控制器中使用“bar”,对吗?

【讨论】:

  • 使用不同的值对我遇到的问题没有影响。这显然是问题的简化测试用例。
【解决方案2】:

由于缺少那个(重要的)部分,让我们确保你同时做这两件事:

[...] 并且 RefreshDatabase 特征被导入到我的测试类中。

您是只导入它还是同时使用它?您的 TestClass 需要如下所示:

<?php

[..]

use Illuminate\Foundation\Testing\RefreshDatabase;

[..]

class YourTest extends TestCase
{
    use RefreshDatabase;

    [..]
   
}

【讨论】:

  • 是的,当谈到导入特征时,类中的 use 语句就是这样做的。类之前的 use 语句没有导入任何东西,它是别名。 php.net/manual/en/language.namespaces.importing.php
  • 确实如此!对不起,没有看你的名声,尽量避免犯初学者的错误......
猜你喜欢
  • 2017-07-13
  • 2022-12-09
  • 2019-02-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多