30 Days of Automated Testing:Using PHPUnit【D20】
Let’s look at Queue Mocking today!
Queue Mocking Functions
Queue::fake()
: When we want to verify that a Job class has been dispatched to the queue during the execution of the target behavior but do not actually trigger the Job enqueueing, we can call this function in the test code.Queue::assertPushed()
: Verifies if the specified Job class has been dispatched to the queue. This can only be used afterQueue::fake()
has been executed.Queue::assertPushedOn()
: Verifies if the specified Job class has been dispatched to the specified queue. This can only be used afterQueue::fake()
has been executed.Queue::assertNotPushed()
: Verifies if the specified Job class has not been dispatched to the queue. This can only be used afterQueue::fake()
has been executed.Queue::assertNothingPushed()
: Verifies if no Job class has been dispatched to the queue. This can only be used afterQueue::fake()
has been executed.
Next, let’s practice and see it in action!
Example:Article View Counting
Test Target:Article view counting endpoint
- database/migrations/2022_10_02_174939_create_articles_table.php
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('articles', function (Blueprint $table) {
$table->id();
$table->text('content');
$table->integer('page_views');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('articles');
}
};
- app/Models/Article.php
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Article extends Model
{
use HasFactory;
protected $fillable = [
'content',
'page_views',
];
}
- database/factories/ArticleFactory.php
<?php
namespace Database\Factories;
use Illuminate\Database\Eloquent\Factories\Factory;
/**
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Article>
*/
class ArticleFactory extends Factory
{
/**
* Define the model's default state.
*
* @return array<string, mixed>
*/
public function definition()
{
return [
'content' => $this->faker->text,
'page_views' => 0,
];
}
}
- app/Jobs/AddArticlePageViewJob.php
<?php
namespace App\Jobs;
use App\Models\Article;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldBeUnique;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
class AddArticlePageViewJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
private $article;
/**
* Create a new job instance.
*
* @return void
*/
public function __construct(Article $article)
{
$this->article = $article;
}
/**
* Execute the job.
*
* @return void
*/
public function handle()
{
$this->article->page_views += 1;
$this->article->save();
}
}
- routes\api.php
<?php
use App\Jobs\AddArticlePageViewJob;
use App\Models\Article;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
Route::post('/article/{id}/page-view', function (Request $request, $id) {
$article = Article::find($id);
if (empty($article)) {
return response()->json([], 404);
}
AddArticlePageViewJob::dispatch($article)->onQueue('redis');
return response('', 200);
});
Test Code:
<?php
namespace Tests\Feature;
use App\Jobs\AddArticlePageViewJob;
use App\Models\Article;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Queue;
use Tests\TestCase;
class QueueTest extends TestCase
{
use RefreshDatabase;
public function testDispatchAddArticlePageViewJob()
{
$article = Article::factory()->create();
Queue::fake();
$response = $this->post(route('add-article-page-views', ['id' => $article->id]));
$response->assertOk();
Queue::assertPushedOn('redis', AddArticlePageViewJob::class);
}
public function testNotDispatchAddArticlePageViewJob()
{
$article = Article::factory()->create();
Queue::fake();
$response = $this->post(route('add-article-page-views', ['id' => $article->id . '0']));
$response->assertNotFound();
Queue::assertNotPushed(AddArticlePageViewJob::class);
}
}
The above test code tests two test cases:
testDispatchAddArticlePageViewJob()
: In this test case function, we verify that when the article view history endpoint is requested and the article exists, theAddArticlePageViewJob
job class is dispatched.testNotDispatchAddArticlePageViewJob()
: In this test case function, we verify that when the article view history endpoint is requested and the article does not exist, theAddArticlePageViewJob
job class is not dispatched.
The above is an introduction to Queue Mocking today. You can practice more.
Next, let’s take a look at Storage Mocking and HTTP Mocking.
If you liked this article or found it helpful, feel free to give it some claps and follow the author!