Laravel包-在测试文件和控制器中体验不同的模型数据

xvw2m8pv  于 2023-08-08  发布在  其他
关注(0)|答案(1)|浏览(74)

我目前正在处理一个Laravel包,下面有路由配置

Route::apiResource('companies', Controllers\CompanyController::class);
Route::apiResource('companies.addresses', Controllers\AddressController::class)->parameter('companies', 'entity');

Route::apiResource('employees', Controllers\EmployeeController::class);
Route::apiResource('employees.addresses', Controllers\AddressController::class)->parameter('companies', 'entity');

字符串
这是控制器

// Http/CompanyController.php

class CompanyController extends Controller
{
    // index, store, show, update, destroy methods are here
}

// Http/EmployeeController.php

class EmployeeController extends Controller
{
    // index, store, show, update, destroy methods are here
}

// Http/AddressController.php

use My\Contracts\Entity;
use My\Http\Requests\AddressStoreRequest;

class AddressController extends Controller
{
    public function index(Entity $entity)
    {
        $items = $entity->addresses()->latest();

        // the code
    }

    public function store(AddressStoreRequest $request, Entity $entity)
    {
        // the code
    }

    // show, update, destroy methods are here
}


这是我的模型

class Company extends Model implements Entity
{
    public function addresses()
    {
        return $this->morphMany(Address::class, 'owner');
    }
}

class Employee extends Model implements Entity
{
    public function addresses()
    {
        return $this->morphMany(Address::class, 'owner');
    }
}

class Address extends Model
{
    // ...
}


这里是ServiceProvider内部

use My\Models\Company;
use My\Models\Employee;
use My\Contracts\Entity;

$this->app->bind(Entity::class, function ($app) {
    return $app->make($app['router']->is('companies.*') ? Company::class : Employee::class);
});


注意到Entity实际上是一个接口,它根据路由名称绑定到一个模型,因为AddressController用于两个不同的路由。
最后一个是我的测试

// the EmployeeTest did pretty much the same
class CompanyTest extends TestCase
{
    #[Test]
    public function should_able_to_retrieve_all_data(): Company
    {
        $models = Company::factory(2)->create();

        $response = $this->getJson('base/companies');

        // the assertion goes here

        return $models->first();
    }

    #[Test]
    #[Depends('should_able_to_retrieve_all_data')]
    public function should_able_to_retrieve_all_addresses(Company $model): void
    {
        $response = $this->getJson("base/companies/{$model->getRouteKey()}/addresses");

        $response->assertOk();
    }
}


除了should_able_to_retrieve_all_addresses之外,其他测试都运行得很好。它总是返回404。最初我以为这是关于隐式模型绑定的,在花了几个小时挖掘之后,我非常确定不是。
直到我像这样将dump(Company::all())添加到我的CompanyTest::should_able_to_retrieve_all_addresses()AddressController::index()方法中

class CompanyTest extends TestCase
{
    #[Test]
    #[Depends('should_able_to_retrieve_all_data')]
    public function should_able_to_retrieve_all_addresses(Company $model): void
    {
        $response = $this->getJson("base/companies/{$model->getRouteKey()}/addresses");
        dump(Company::all()->toArray());

        $response->assertOk();
    }
}

class AddressController extends Controller
{
    public function index(Entity $entity)
    {
        dump(Company::all()->toArray());
    }
}


我发现测试文件中的一个可以返回所有可用的公司,但是控制器中的一个返回一个空数组。怎么可能呢?
您可以找到存储库here

chhkpiq4

chhkpiq41#

又花了一个小时,发现我所需要的就是在每个测试方法中调用模型工厂,而不是像这样使用测试依赖项

#[Test]
public function should_able_to_retrieve_all_addresses(): void
{
    $model = Company::factory()->createOne();

    $response = $this->getJson("base/companies/{$model->getRouteKey()}/addresses");

    $response->assertOk();
}

字符串
我还必须像这样更新容器条目,以自己解决路由绑定,而不是依赖于隐式模型绑定

$this->app->bind(Entity::class, function ($app) {
    $router = $app->make('router');
    $entity = $app->make($router->is('companies.*') ? Company::class : Employee::class);

    return $entity->resolveRouteBinding($router->input('entity')) ?: $entity;
});


的确,它起作用了。但是为什么我不知道。

相关问题