【问题标题】:Laravel Feature/Unit TestingLaravel 功能/单元测试
【发布时间】:2021-09-07 02:54:27
【问题描述】:

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

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

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

所以,我的问题:

  • 为什么测试没有发现这个问题,尽管在某些情况下我的编辑调用确实为该属性发送了 false
  • 您为代码编写的测试有多详细?您是否正在使用有效和无效数据测试任何可能的结果,进行大量测试?因为测试所有可能的组合会增加测试的数量。

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

迁移:

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]:违反完整性约束:1048 列“invoice_details”不能为空(SQL:更新clients 设置invoice_details = ?,clients.updated_at = 2021-06-23 13:14 :15 其中id = 1)

【问题讨论】:

    标签: laravel laravel-testing


    【解决方案1】:

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

    测试的想法是测试一切,你写到不确定是要写很多测试还是去做。简短的回答是yes,去做吧,因为这就是想法,测试非常可能的结果。

    有些端点实际上是 2 次测试,有些是 30 次……你没有发现这个 true/false (null) 问题,因为你没有测试得到错误值的端点,null在这种情况下或任何会创造该价值的情况下。

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

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

    【讨论】:

    • 是的,谢谢你确认我的想法。
    • 别担心,只要记住测试就是为了这个,测试每一个结果
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-24
    • 2017-12-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多