在单元测试中传递参数,在数据库 CRUD 中更新函数 Laravel

Passing parameters in an Unit Test, function update in database CRUD Laravel

我一直在创建一些测试来尝试从我的数据库中在 laravel 上创建删除编辑功能,这是我的代码:

ConstituencyController.php :

<?php

namespace App\Http\Controllers;

use App\Http\Requests\StoreConstituencyRequest;
use App\Http\Resources\ConstituencyResource;
use App\Models\Constituency;
use Illuminate\Http\Request;
use phpDocumentor\Reflection\Types\Collection;

class ConstituencyController extends Controller
{


    /**
     * Display a listing of the constituencies.
     *
     *
     */
    public function index()
    {
        $constituency = Constituency::all();

        return ConstituencyResource::collection($constituency);
    }



    /**
     * Show the form for creating a new resource.
     *
     *
     */
    public function create()
    {
        //
    }



    /**
     * Store a newly created constituency in storage.
     *
     * @param Request $request
     *
     */
    public function store(Request $request)
    {
        $name = $request->name;
        $data = array("name"=>$name);

        Constituency::insert($data);
    }



    /**
     * Display the specified constituency.
     *
     * @param  int $id
     *
     */
    public function show(int $id)
    {
        $constituency = Constituency::find($id);

        return new ConstituencyResource($constituency);
    }



    /**
     * Show the form for editing the specified resource.
     *
     * @param  int  $id
     *
     */
    public function edit(int $id)
    {
        //
    }



    /**
     * Update the specified constituency in storage.
     *
     * @param Request $request
     * @param  int  $id
     *
     */
    public function update(Request $request, int $id)
    {
        $constituency = Constituency::find($id);
        $constituency->name = $request->name;

        $constituency->update();
    }



    /**
     * Remove the specified constituency from storage.
     *
     * @param  int  $id
     *
     */
    public function destroy(int $id)
    {
        Constituency::find($id)->delete();
    }
}

Constituency.php:

<?php

namespace App\Models;

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

class Constituency extends Model
{
    use HasFactory;

    public function candidate()
    {
        return $this->hasMany(Candidate::class);
    }

    public function town()
    {
        return $this->hasMany(Town::class);
    }
}

ConstituencyResource.php :

    <?php
    
    namespace App\Http\Resources;
    
    use Illuminate\Http\Resources\Json\JsonResource;
    
    class ConstituencyResource extends JsonResource
    {
        /**
         * Transform the resource into an array.
         *
         * @param  \Illuminate\Http\Request  $request
         * @return array|\Illuminate\Contracts\Support\Arrayable|\JsonSerializable
         */
        public function toArray($request)
        {
            return [
                'id' => $this->id,
                'name' => $this->name,
                'created_at' => $this->created_at,
                'updated_at' => $this->updated_at,
            ];
        }
    
    
    }

ConstituencyFactory.php :

<?php

namespace Database\Factories;

use Illuminate\Database\Eloquent\Factories\Factory;

/**
 * @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Constituency>
 */
class ConstituencyFactory extends Factory
{
    /**
     * Define the model's default state.
     *
     * @return array<string, mixed>
     */
    public function definition()
    {
        return [
            'name' => $this->faker->word(),
        ];
    }
}

现在这是我更新选区的测试:

public function test_a_constituency_can_be_modified()
    {
        $constituency = Constituency::factory()->create();
        $constituency_id = $constituency->id;

        $response = $this->put('api/constituencies/'.$constituency_id);

        $this->assertDatabaseHas('constituencies', [
            'id' => $constituency->id,
            'name' => $constituency->name,
            'created_at' => $constituency->created_at,
            'updated_at' => $constituency->updated_at,
        ]);
    }

现在当然测试通过了,但我实际上并没有给它一些新的参数来改变...我一直在尝试给函数一些参数来实际改变一些数据,但我不能弄清楚该怎么做....我认为我不必将参数放在 URI 中,但那又在哪里呢?

如果您正在使用 PHPUnit you likely want to make use of Data Providers:

来自文档的示例

/**
 * @dataProvider additionProvider
 */
public function testAdd(int $a, int $b, int $expected): void
{
    $this->assertSame($expected, $a + $b);
}

public function additionProvider(): array
{
    return [
        'adding zeros'  => [0, 0, 0],
        'zero plus one' => [0, 1, 1],
        'one plus zero' => [1, 0, 1],
        'one plus one'  => [1, 1, 3]
    ];
}

Tighten 的聪明人也有 excellent tutorial on data providers

如果您正在使用 PEST then you'll want Data Sets

来自文档的示例

dataset('emails', [
    'enunomaduro@gmail.com',
    'other@example.com'
]);

it('has emails', function ($email) {
    expect($email)->not->toBeEmpty();
})->with('emails');  // <-- use the dataset

使用数据提供者和数据集可以让您重复使用数据,还可以针对单元测试的多个输入进行测试。如果您只想在排列语句(创建数据库记录的位置)后硬编码一个值,那么您可以这样做,但这样做有局限性,而且提供程序要灵活得多。

更新 - 示例测试

以下是您可能如何处理事情的示例。请注意,这并不详尽,并且不建议使用 $request->all() 来更新您的模型,但我这样做是为了使事情简单明了。这应该让您了解 where/how 您可以着手执行测试。这样的事情有很多ways/opinions

api.php

Route::put('/constituencies/{constituency}', 
    [ConstituencyController::class, 'update']
)->name('api.constituencies.update');

ConstituencyController.php

<?php

namespace App\Http\Controllers;

use App\Models\Constituency;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;

class ConstituencyController extends Controller
{
    public function update(Request $request, Constituency $constituency)
    {
        $constituency->update($request->all());

        return response()->json($constituency, Response::HTTP_OK);
    }
}

ExampleTest.php

<?php

namespace Tests\Feature;

use Tests\TestCase;
use App\Models\Constituency;
use Symfony\Component\HttpFoundation\Response;
use Illuminate\Foundation\Testing\RefreshDatabase;

class ExampleTest extends TestCase
{
    /**
     * A basic test example.
     *
     * @test
     * @dataProvider constituencyNameProvider
     * @return void
     */
    public function it_can_update_constituency_name_successfully($constituencyName)
    {
        // Arrange
        $constituency = Constituency::factory()->create();
        $payload = ['name' => $constituencyName];

        // Act
        $response = $this->put(route('api.constituencies.update', $constituency->id), $payload);

        // Assert
        $response->assertStatus(Response::HTTP_OK)
            ->assertJson([
                'id' => $constituency->id,
                'name' => $constituencyName
            ])
            ->assertJsonStructure([
                'id', 'name', 'created_at', 'updated_at'
            ]);
    }

    public function constituencyNameProvider(): array
    {
        return [
            ['Ostwald'],
            ['Springtown'],
            ['Baybarrow'],
            ['Blackhaven'],
            ['Lochspring'],
        ];
    }
}