Laravel Feature/Unit 测试

Laravel Feature/Unit Testing

由于我在 Laravel 方面还是个初学者,所以我偶然发现了一个有趣的测试问题,需要第二个意见。

我编写了模型、控制器、视图、工厂、播种器,然后是(功能)测试。测试确实涵盖了很多(不会说全部),但我只是发现了一个测试没有发现的问题,尽管它应该。测试主要通过调用 HTTP 端点来完成,因此理论上它应该像用户一样显示、添加、编辑和删除数据。工厂正在确保输入的数据与用户输入的数据大致相同(请让我们在本次演讲中排除欺诈用户,这可以更改 HTTP POST 请求)。

所以问题是模型的属性接受 truefalse,工厂只为该属性生成这两个值,但在编辑时在控制器中我错误地设置了值是否为 false目前,它将值设置为 null。 St运行gely,尽管我运行进行了很多测试,这个问题以前从未出现过,只有在我手动尝试更新模型时才会出现。

所以,我的问题:

一些代码,因为我知道你们中的一些人会问(注意我只会添加相关部分,而不是所有内容):

迁移:

class CreateClientsTable extends Migration
{
    public function up()
    {
        Schema::create('clients', function (Blueprint $table) {
            $table->id();
            ...
            $table->boolean('invoice_details')->default(false);
            ...
        });
    }
    public function down()
    {
        Schema::dropIfExists('clients');
    }
}

型号:

class Client extends Model
{
    use HasFactory;

    protected $fillable = [
        ...
        'invoice_details',
        ...
    ];

    ...

    protected static function newFactory(): Factory
    {
        return ClientFactory::new();
    }
}

控制器:

class ClientController extends Controller
{
    ...
    
    public function edit(int $id): View
    {
        $data = Client::findOrFail($id);
        return view('client::edit', compact('data'));
    }

    public function update(UpdateClientRequest $request, int $id)
    {
        $client = Client::findOrFail($id);

        $response = $client->update([
            ...
            'invoice_details' => $request->invoice_details ?? null, // NOTE THE NULL, THIS TRIGGERED THE ERROR
            ...
        ]);

        ...
        
        return CustomResponse::resource($request, 'update', $response, route('client.index'), Client::findOrFail($id));
    }
}

工厂:

class ClientFactory extends Factory
{
    protected $model = Client::class;

    public function definition(): array
    {
        $details = [
            ...
            'invoice_details' => $this->faker->randomElement([true, false]),
        ];

        if ($details['invoice_details']) {
            ...
        }

        return $details;
    }
}

播种机:

class ClientsSeeder extends Seeder
{
    public function run()
    {
        $client = Client::factory()->create();
    }
}

错误:

SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'invoice_details' cannot be null (SQL: update clients set invoice_details = ?, clients.updated_at = 2021-06-23 13:14:15 where id = 1)

我正在用手机写作,所以请记住这一点。

测试的想法是测试一切,你写道不确定是否要写很多测试或做。简短的回答是 yes,去做吧,因为这就是想法,测试所有可能的结果。

有的端点真的是2个测试,有的是30...你没抓到这个true/false (null)问题,因为你没有测试端点得到错误的值,null 在这种情况下或任何会创建该值的值。

所以你必须发送一个错误的属性(值)并期待一个错误返回,当这种情况发生时,你的测试通过。使用 $response->assertSessionHasError('invoice_details')。在文档中查找它,因为您可以传递像 ['attribute_name' => 'expected error message'].

这样的数组

如果您有更多问题,请更新您的问题或使用您的代码创建一个新问题。