【问题标题】:Laravel - Unit test - variable of integer data type is coming as string while unit testing and the unit test is failingLaravel - 单元测试 - 整数数据类型的变量在单元测试和单元测试失败时以字符串形式出现
【发布时间】:2018-09-05 08:00:05
【问题描述】:

我是 Laravel 和 PHP 的新手。我创建了一个迁移“汽车”表,其中包含 id、Make、Model、Year 列。我使用播种机使用 faker 制造了 50 辆汽车。 我已经编写了一个单元测试来测试 year 属性的数据类型是否为 int,但是我的单元测试失败了。谁能帮我解决这个问题?

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);
    }

【问题讨论】:

  • 首先,您不需要为您的数据库播种以进行测试。从技术上讲,测试是在不同的数据库中完成的。如果您想使用生产数据库,请确保您有连接到生产数据库的 .testing.env。
  • 您是否在模型中使用类型转换?
  • 您遇到了这个问题:github.com/laravel/framework/issues/3548

标签: php laravel unit-testing


【解决方案1】:

不确定数据类型是否是正确的测试类型,但无论如何

要记住的关键是你需要有一个不同的数据库来测试我使用内存的情况,所以我的 phpunit.xml 如下所示

<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:"/>

你将有你的测试课。在您的情况下,我将其称为 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));
    }
}

【讨论】:

    【解决方案2】:

    尝试更新您的模型以防止与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',
    ];
    

    【讨论】:

      【解决方案3】:

      这可能是您的问题中的拼写错误,但字段区分大小写。 $car-&gt;year 将为您提供 year 字段中的值。 $car-&gt;Year 会给你null,因为你没有Year 字段。

      至于从数据库返回的字段类型,可能会因底层数据库和用于访问该数据库的驱动程序而异。如果您想避免所有不确定性,则需要将您的字段添加到模型的 $casts 属性中:

      protected $casts = [
          'year' => 'int',
      ];
      

      现在该字段在访问时将始终转换为 PHP 整数。

      【讨论】:

        【解决方案4】:

        我猜你正在使用内存中的 SQLite 数据库进行测试:

        <server name="DB_CONNECTION" value="sqlite"/>
        <server name="DB_DATABASE" value=":memory:"/>
        

        如果是这样,那么您遇到了这个问题:

        https://github.com/laravel/framework/issues/3548

        它于 2014 年关闭,但从未真正修复。你有两个选择:

        1. 从 SQLite 中的测试切换到在生产中使用的同一数据库引擎中进行测试。
        2. 明确typecast模型中的所有键。

        对于第二个选项,您的 Car 模型应该具有将 id 转换为 integer$casts 属性:

        protected $casts = [
            'id' => 'integer',
        ];
        

        必须显式转换键的权衡可能值得保持 SQLite 提供的速度。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-11-25
          • 2015-02-05
          • 2018-10-27
          • 2011-08-23
          • 1970-01-01
          • 2019-12-12
          相关资源
          最近更新 更多