php - 我应该如何在 Laravel 中正确构建我的单元测试

标签 php unit-testing phpunit laravel-8 factory-pattern

我对单元测试很陌生,需要一些指导。我正在尝试使用 Laravel 和 phpunit 中的工厂模式为应用程序编写一个简单的单元测试,该应用程序允许您将公司添加到数据库。

我有一个公司模型Company.php,一个使用它的工厂类CompanyFactory.php,最后是单元测试本身CompaniesTest.php.

模型/Company.php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Company extends Model
{
    use HasFactory;
    protected $table = 'companies';
    protected $fillable = [
        'name',
        'email'
    ];
}

数据库/工厂/CompanyFactory.php

namespace Database\Factories;

use App\Models\Company;
use Illuminate\Database\Eloquent\Factories\Factory;

class CompanyFactory extends Factory
{
    /**
     * The name of the factory's corresponding model.
     *
     * @var string
     */
    protected $model = Company::class;

    /**
     * Define the model's default state.
     *
     * @return array
     */
    public function definition()
    {
        return [
            'name' => $this->faker->name,
            'email' => $this->faker->email,
            'created_at' => now(),
            'updated_at' => now(),
        ];
    }
}

测试/功能/CompaniesTest.php

namespace Tests\Unit;
        
use Illuminate\Foundation\Testing\DatabaseTransactions;
use App\Models\Company;
use Tests\TestCase;
use Illuminate\Support\Str;
use Illuminate\Foundation\Testing\WithFaker;

class CompanyTest extends TestCase
{
    use WithFaker, DatabaseTransactions;

    public function createCompany($name = NULL)
    {
        if ($name == NULL) $name = Str::random(6);

        $company = Company::factory()->create([
            'name' => 'TestName_'.$name
        ]);

        return $company->id;
    }


    /** @test */
    public function company_can_be_created()
    {
        $name = Str::random(6);

        //Create a company
        $company_id = $this->createCompany($name);

        //Check whether the company name exists in the database
        $this->assertDatabaseHas('companies', [
            'name' => 'TestName_'.$name
        ]);
    }
}

测试似乎有效,但感觉我可能过于复杂,并且可能没有遵循正确的约定。

更好的构建方式是什么?

最佳答案

测试看起来不错,但你实际上在测试什么?在我看来,这个测试是在测试框架的代码,这实际上不是你应该做的。

不要测试工厂,用它来准备每次测试之前所需的数据。然后运行您想要测试的实际代码,并断言结果。


更新:继续使用CompanyVerifier(请参阅评论)。假设公司可以是有效无效。可以验证有效的公司。那么测试可能如下所示:

/** @test */
public function test_valid_company_can_be_verified()
{
    // here use a CompanyFactory with some pre-defined data to create "valid" company
    $validCompany = $this->createValidCompany();

    // here goes the actual code of SUT (system under test)
    $verifier = new CompanyVerifier();
    $result = $verifier->verify($validCompany);

    // here check results
    $this->assertTrue($result);
}

测试的良好实践称为 AAA (arrange-act-assert)。在这里,创建具有某种状态的公司是一个“安排”阶段。运行经过测试的代码是“act”。而assert就是“断言”。

工厂只是“安排”阶段的 helper 。

关于php - 我应该如何在 Laravel 中正确构建我的单元测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68271050/

相关文章:

java - Jenkins 不会运行 PHPUunit - 权限被拒绝

php - 在实时 Windows 服务器上安装 Wordpress?

php - 带变量的复杂sql查询

php - json_encode 不会编码超过 6670 行

c# - mbunit v3 文档

laravel - 在PhpUnit测试中匹配JsonStructure-Laravel 5.4

javascript - HTML 发布数组 仅发布第一个值

visual-studio-2010 - VS2010 单元测试 “Pending” 无法完成测试

c# - 模拟 rabbitMQ IModel 验证错误

带有 Zend 框架的 PHPUnit