Reputation: 41
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);
}
Upvotes: 3
Views: 2748
Reputation: 352
I'm guessing that you are using an in-memory SQLite database for testing:
<server name="DB_CONNECTION" value="sqlite"/>
<server name="DB_DATABASE" value=":memory:"/>
If so, then you are running into this issue:
https://github.com/laravel/framework/issues/3548
It was closed in 2014, but never actually fixed. You have two options:
For the second option, your Car
model should have a $casts
attribute that casts id
to integer
:
protected $casts = [
'id' => 'integer',
];
The trade-off of having to explicitly cast keys might be worth keeping the speed that SQLite provides.
Upvotes: 3
Reputation: 2830
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));
}
}
Upvotes: 1
Reputation: 62398
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.
Upvotes: 0
Reputation: 4285
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',
];
Upvotes: 1