【问题标题】:How should I correctly construct my unit test in Laravel我应该如何在 Laravel 中正确构建我的单元测试
【发布时间】:2021-09-17 02:46:03
【问题描述】:

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

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

Models/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'
    ];
}

Database/Factories/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(),
        ];
    }
}

Tests/Feature/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
        ]);
    }
}

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

有什么更好的方式来构建它?

【问题讨论】:

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


    【解决方案1】:

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

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


    更新:继续使用CompanyVerifier(参见 cmets)。假设公司可以是validnon-valid。可以验证有效的公司。那么测试可能如下所示:

    /** @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)。在这里,创建具有某种状态的公司是一个“安排”阶段。运行测试代码是“行为”。并且断言是“断言”。

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

    【讨论】:

    • 这听起来不错。您能否添加一些代码来说明。我觉得我对此有心理障碍。
    • 我向您推荐 Vladimir Khorikov 的一本很棒的书“单元测试的原则”。
    • 想想你想要测试的“行为单元”。例如,您有一个服务 CompanyVerifier,它使用一些重要的域逻辑来验证公司。并且您要确保此逻辑正常工作。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-07-23
    • 2015-05-22
    • 2021-11-19
    • 2021-11-22
    • 2012-10-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多