因为测试效果不佳,phpunit 在 laravel?



我有以下设置:

config/database.php

特别是:"连接">

'testing' => [
'driver'            => 'mysql',
'url'               => env('DATABASE_URL'),
'host'              => env('TEST_DB_HOST'),
'port'              => env('TEST_DB_PORT', '5432'),
'database'          => env('TEST_DB_DATABASE', 'forge'),
'username'          => env('TEST_DB_USERNAME', 'forge'),
'password'          => env('TEST_DB_PASSWORD', ''),
'charset'           => 'utf8',
'prefix'            => '',
'prefix_indexes'    => true,
'schema'            => 'public',
'sslmode'           => 'prefer'
],

in.env

TEST_DB_CONECTION=testing
TEST_DB_HOST=mysql-db
TEST_DB_PORT=3306
TEST_DB_DATABASE=db_test
TEST_DB_USERNAME=root
TEST_DB_PASSWORD=secret_test

我的所有文件phpunit.xml

<?xml version="1.0" encoding="UTF-8"?>
<phpunit backupGlobals="false"
backupStaticAttributes="false"
bootstrap="vendor/autoload.php"
colors="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="true"
stopOnFailure="false">
<testsuites>
<testsuite name="Feature">
<directory suffix="Test.php">./tests/Feature</directory>
</testsuite>
<testsuite name="Unit">
<directory suffix="Test.php">./tests/Unit</directory>
</testsuite>
</testsuites>
<filter>
<whitelist processUncoveredFilesFromWhitelist="true">
<directory suffix=".php">./app</directory>
</whitelist>
</filter>
<php>
<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="MAIL_DRIVER" value="array"/>
<env name="DB_CONNECTION" value="sqlite"/>
<env name="DB_DATABASE" value="db_test"/>
</php>
</phpunit>

在我的测试类中

use RefreshDatabase;
protected $user;
public function setUp() : void {
parent::setUp();
$this->user = factory(User::class)->create();
$this->actingAs($this->user);
}
public function testCreateExcessCarriers(){
var_dump("some text to try");
}

执行时:

docker-compose exec utraq vendor/bin/phpunit tests/Unit/Http/Controllers/ECControllerTest.php --filter testCreateExcessCarriers

我得到这个错误:

Illuminate\Database\QueryException:SQLSTATE[HY000]:一般错误:1无法添加默认值为NULL的NOT NULL列(SQL:alter table"用户";添加列";agency_ id";整数不为空(

通过这种方式,我配置了工厂,与模型检查一切正常

$factory->define(AppModelsUser::class, function (Faker $faker) {
static $password;
return [
'uuid' => $faker->uuid,
'name' => $faker->name,
'email' => $faker->unique()->safeEmail,
'password' => $password ?: $password = bcrypt('secret'),
'active' => 1,
'agency_id' => 3,
];
});

然而,我不知道为什么在执行命令后会出现这个错误。我该如何更正?

编辑:迁移,我想我得到了错误。对于Users表,有2个迁移。

迁移1:

Schema::create('users', function (Blueprint $table) {
$table->increments('id');
$table->string('uuid');
$table->string('name');
$table->string('email')->unique();
$table->string('password');
$table->string('address1')->nullable(); //Address 1
$table->string('address2')->nullable(); //Address 2
$table->string('city')->nullable(); //City
$table->string('state_name')->nullable(); //State
$table->integer('state_id')->nullable(); //State
$table->string('zip_code', 10)->nullable(); //Zip Code    
$table->string('employee_type')->nullable();
$table->dateTime('last_logged_in')->nullable();
$table->json('dashboard')->nullable();
$table->rememberToken();
$table->timestamps();
});

迁移2:正如您所看到的,这就是agency_id字段被分配的地方

Schema::table('users', function (Blueprint $table) {
$table->integer('agency_id')->after('password');
$table->boolean('active')->after('remember_token')->default('0');
$table->boolean('verified')->after('active')->default(false);
$table->string('avatar')->nullable();
});

根据您的问题,我假设您实际上想要使用您定义为"的mysql测试数据库;测试";联系

但是在phpunni配置中,您使用

<env name="DB_CONNECTION" value="sqlite"/>
<env name="DB_DATABASE" value="db_test"/>

这显然与sqlite连接有关。其他人已经指出了sqlite和添加不可为null的列的问题

您可能想更改与DB_DATABASE条目的连接并将其删除

<env name="DB_CONNECTION" value="testing"/>

编辑:

TEST_DB_CONECTION=testing

似乎没有在任何地方使用?还有一个拼写错误:(-可能会从你的env以及中删除

请参阅此答案;https://stackoverflow.com/a/33416155/8068675

如果您需要向现有表中添加一个不可为null的列,那么SQLite似乎只是让您处于一个糟糕的状态,该列也不应该有默认值

简而言之,要解决问题,您有三种可能性;

  • 使用您在生产中使用的相同DB引擎来运行测试。速度较慢,但如果有问题的话,你肯定会看到同样的问题
  • 更改为可为null:$table->integer('agency_id')->nullable()->after('password');
  • (我绝对不推荐,因为它是外键(添加默认值:$table->integer('agency_id')->default(1)->after('password');

根据我的经验,这归结为sqlite无法在没有默认值的情况下将不可为null的列添加到现有表中的限制。

我们使用的解决方案是在同一迁移中将迁移分为两个步骤。第一步将列添加为可为null的&下一步将其更新为不可为null。

所以您的迁移看起来像这样(未经测试(:

Schema::table('users', function (Blueprint $table) {
$table->integer('agency_id')->nullable()->after('password');
});
Schema::table('users', function (Blueprint $table) {
$table->integer('agency_id')->nullable(false)->change();
});

原则上,这是我们使用的,但可能不适用于所有用例。如果能更好地适应您的用例,您可能希望在第一步中设置一个默认值,而不是将其设为null。

如果我没记错的话,nullable(false)中的错误参数后来才在Laravel 5.x中可用,所以这可能不起作用,这取决于您使用的Laravel版本

最新更新