lundi 23 janvier 2017

Laravel preparing the database before a test for a model with many dependencies, is there a better way?

I am using Laravel 5.2 for my web app and the bundled testing tools which extend PHPUnit.

I am writing a test for a page that performs an update on a model, the test simply checks that one of the model's attributes hasn't changed prior to submitting the form in order to prevent two users from updating the model if they had it both open in their browser at the same time.

The test requires the use of a model in my Laravel web app, namely App\Models\Application, and I am using factories to create some fake data for this model. The Application model has many belongsTo relationships, which in turn requires that the related model is created within the test prior to the creation of the Application model. For example, the Application model has a belongsTo relationship with Applicant, so I need to create an Applicant model with a factory prior to creating an Application and an Applicant also has belongsTo relationships with User, which I also need to create before ... you get the idea. So, in short, I am creating several model instances due to the dependency of one model which I want to test.

So this has left me wondering if I am taking the wrong approach? Is there a more simple approach where I can only create the model that is under test?

Here's the code from my test:

/** 
 * @test
 */
public function throw_exception_when_application_status_is_modified_after_submission()
{
    /**
     * Arrange
     */
    // create roles
    factory(Role::class, 'admin')->create();
    factory(Role::class, 'applicant')->create();

    // create admin user
    $adminUser = factory(User::class)->create();
    $adminUser->attachRole(Role::whereName('admin')->first());
    // create applicant user
    $applicantUser = factory(User::class)->create();
    $applicantUser->attachRole(Role::whereName('applicant')->first());

    // create organisation with type
    $organisationType = factory(OrganisationType::class)->create();
    $organisation = factory(Organisation::class)->create();
    $organisation->organisationTypes()->attach($organisation->id);

    // create sub application
    $subApplication = factory(ExperienceLetter::class)->create();

    // create applicant
    $applicant = factory(Applicant::class)->create([
        'user_id' => $applicantUser->id
    ]);

    // create application
    $application = factory(Application::class)->make([
        'status' => 'pending',
        'application_id' => $subApplication->id,
        'application_type' => 'App\Models\ExperienceLetter',
        'organisation_id' => $organisation->id,
        'applicant_id' => $applicant->id,
    ]);    

    // prep data
    $data = [
        'action' => 'accept',
        'details' => 'email sent',
        'application_id' => $application->id,
        'application_status' => 'pending',
        'verification' => 'email',
    ];

    /**
     * Act
     */
    // log in
    $this->actingAs($adminUser);

    // alter status before call()
    $application->status = 'verification';
    $application->save();

    $response = $this->call('POST', route('admin.application.action.store'), $data);

    /**
     * Assert
     */
    $this->assertEquals(302, $response->status());
    // assertSessionHasErrors
}

Thanks for any advice.

Aucun commentaire:

Enregistrer un commentaire