0

I'm new in Laravel. I have 2 tables Productions and Products. Also, I have 2 factories ProductionFactory and ProductFactory. I want to test them via phpunit. Their connection is via production_id.

Error is ErrorException: Undefined variable: production.

I don't get it.

Thanks in advance.

This is a code.

ProductionFactory.php

        $factory->define(App\Production::class, function (Faker $faker) {
        return [
                'name' =>$faker->name,
            ];
          });

ProductFactory.php

       $factory->define(App\Product::class, function (Faker $faker) {
        $production_id = App\Production::pluck('id');

       if(!$production_id->isEmpty()){
          $production = $production_id->random();
       }

    return [
             'id' =>$faker->uuid,
             'name' =>$faker->name,
             'price' => $faker->numberBetween($min = 100, $max = 900),
             'description' =>Str::random(10),
             'production_id'=> $production,
          ];

ProductionTest.php

           class ProductionTest extends TestCase
            {
              use RefreshDatabase;

             /**
             * A basic unit test example.
             * @test
             * @return void
               */
            public function production()
               {
                   factory(Production::class)->make();
                   $this->assertTrue(true);
               }
           }

ProductTest.php

           class ProductTest extends TestCase
            {
              use RefreshDatabase;

             /**
             * A basic unit test example.
             * @test
             * @return void
               */
            public function product()
               {
                   factory(Product::class)->make();
                   $this->assertTrue(true);
               }
           }
JohnnyJP
  • 7
  • 5

2 Answers2

0

It depends on what functionality should be tested.

A basic test to check the model relationship is set correctly?

I pushed a working demo to GitHub (https://github.com/.../laravel-basic-relationship-tests).

App/Product.php

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Product extends Model
{
    public function production()
    {
        return $this->belongsTo(Production::class);
    }
}

App/Production.php

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Production extends Model
{
    public function products()
    {
        return $this->belongsTo(Product::class);
    }
}

Product Factory

<?php

/* @var $factory \Illuminate\Database\Eloquent\Factory */

use App\Product as Model;
use Faker\Generator as Faker;

$factory->define(Model::class, function (Faker $faker) {
    $production = factory(\App\Production::class)->make();
    $production->save();

    return [
        'name' => $faker->name,
        'price' => $faker->numberBetween($min = 100, $max = 900),
        'description' => $faker->text,
        'production_id' => $production->id
    ];
});

Production Factory

<?php

/* @var $factory \Illuminate\Database\Eloquent\Factory */

use App\Production as Model;
use Faker\Generator as Faker;

$factory->define(Model::class, function (Faker $faker) {
    return [
        'name' => $faker->name
    ];
});

$factory->afterCreatingState(Model::class, 'seed', function ($production, $faker) {
    $product = factory(\App\Product::class)->make();
    $production->products()->associate($product);
});

Product Test

<?php

namespace Tests\Feature;

use Tests\TestCase;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Foundation\Testing\RefreshDatabase;

class ProductTest extends TestCase
{
    /**
     * @return void
     */
    public function testProductHasWorkingProductionRelationship()
    {
        $product = factory(\App\Product::class)->create();
        $this->assertNotEmpty($product->production);
    }
}

Production Test

<?php

namespace Tests\Feature;

use Tests\TestCase;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Foundation\Testing\RefreshDatabase;

class ProductionTest extends TestCase
{
    /**
     * @return void
     */
    public function testProductionHasWorkingProductRelationship()
    {
        $production = factory(\App\Production::class)->state('seed')->create();
        $this->assertNotEmpty($production->products);
    }
}

Hope this is a great starting point for any further tests.

Jonas
  • 42
  • 5
  • I have an error. SQLSTATE[HY000]: General error: 1364 Field 'production_id' doesn't have a default value. Production_id is foreign key in table Products, which is related to primary id in table Productions. – JohnnyJP Jun 01 '19 at 09:50
  • I think this is a migration issue. Compare your migrations with [these](https://github.com/jonasemde/laravel-basic-relationship-tests/tree/master/database/migrations). – Jonas Jun 01 '19 at 14:39
  • You use nullable properties in columns. I mustn't use that kind of columns. I know it's a complex problem. Btw, your method works good, but I hope so there is another way to solve this problem, without nullable. – JohnnyJP Jun 01 '19 at 14:58
  • I edited the answer. It should now work without a production_id nullable field. – Jonas Jun 06 '19 at 08:59
  • You're right. But, as you can see, my model Production is a little bit different then yours. I have function products() {return $this->hasMany(App\Product::class);} As regards to model Product, it's the same. – JohnnyJP Jun 06 '19 at 23:01
0

Model Production

      use Illuminate\Database\Eloquent\SoftDeletes;

       class Production extends Model
       {
            use SoftDeletes;
              protected $fillable = [
                 'name',
              ];
             public function products()
               {
              return $this->hasMany('App\Product');

               }

Model Product

      class Product extends Model
          {

              use SoftDeletes;
               protected $fillable = [
              'id','name','price','description','production_id'
               ];
           public function production()
          {
             return $this->belongsTo('App\Production');
            }

SQLSTATE[HY000]: General error: 1364 Field 'production_id' doesn't have a default value

JohnnyJP
  • 7
  • 5