I'm new to Laravel and PHP. I have created a migration 'Car' table with columns id, Make, Model, Year.I have used the seeder to make 50 cars using faker. I have written a unit test to test the data type of the year property to be int, but my unit test is failing. Could anyone pls help me on this?
Migration table:
public function up()
{
Schema::create('cars', function (Blueprint $table) {
$table->increments('id');
$table->string('make');
$table->string('model');
$table-> integer('year');
$table->timestamps();
});
Factory:
$factory->define(App\Car::class, function (Faker $faker) {
return [
'make' => $faker->randomElement($array = array ('Ford','Honda','Toyota')),
'model' => $faker->name,
'year' => $faker->year($max = 'now'),
Seeder
public function run()
{
factory(App\Car::class, 50)->create()->each(function ($car)
}
Unit test
public function testCarYearDataType()
{
$car = Car::find(1);
dd($car->year);
dd(gettype($car->Year));
this->assertInternalType('int',$car->Year);
}
Not sure datatype is the right kind of test but anyway
The key thing to remember is you need to have a different database for testing my case I use memory so my phpunit.xml looks like the following
<env name="APP_ENV" value="testing"/>
<env name="CACHE_DRIVER" value="array"/>
<env name="SESSION_DRIVER" value="array"/>
<env name="QUEUE_DRIVER" value="sync"/>
<env name="DB_CONNECTION" value="sqlite"/>
<env name="DB_DATABASE" value=":memory:"/>
The you will have your test class. In your case I would call it CarTest.php
<?php
namespace Tests\Unit;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Tests\TestCase;
class CarTest extends TestCase {
use DatabaseTransactions;
public function testCarYearDataType()
{
//just create 1 car as all the cars will have same data type anyway
factory(App\Car::class)->create();
this->assertInternalType('int', gettype(Car::first()->year));
}
}
</div>
Try updating your model to prevent these collisions with typecasting:
/**
* The attributes that are not mass assignable.
*
* @var array
*/
protected $guarded = [
'id',
];
/**
* Typecasting is awesome and it prevents errors.
*
* @var array
*/
protected $casts = [
'make' => 'string',
'model' => 'string',
'year' => 'integer',
];
/**
* The attributes that should be mutated to dates.
*
* @var array
*/
protected $dates = [
'created_at',
'updated_at',
];
It may be a typo in your question, but fields are case sensitive. $car->year
will give you the value in your year
field. $car->Year
will give you null
, since you don't have a Year
field.
As for the type of the field returned from the database, that can differ depending on the underlying database and the drivers used to access that database. If you want to avoid all uncertainty, you need to add your field to your $casts
attribute on your model:
protected $casts = [
'year' => 'int',
];
Now the field will always be cast to a PHP integer when accessed.