TDD Laravel - laravel 和 spatie/laravel-activitylog 中的功能测试出现 JSON 编码错误
TDD Laravel - Feature test in laravel and spatie/laravel-activitylog get JSON encoding errors
我正在 laravel 中为我的模型编写一些测试,当我使用 spatie/laravel-activitylog.
启用 Activity 日志时遇到了一些麻烦
所以,我创建了一个用户,使用 Factory
,我在系统中进行了身份验证,当我尝试注销时,我得到了这个错误:
1) Tests\Feature\Usuario\CriarUsuarioTest::testAcessaPaginaDeRegistro
Illuminate\Database\Eloquent\JsonEncodingException: Unable to encode attribute [properties] for model [Spatie\Activitylog\Models\Activity] to JSON: Type is not supported.
我的测试TestCase.php
:
protected function setUp()
{
parent::setUp();
$this->user = create('App\Models\Usuario');
$this->singIn($this->user)
->disableExceptionHandling();
}
...
...
...
protected function singIn($user)
{
$this->actingAs($user);
return $this;
}
protected function singOut()
{
// routeLogout() goes to '/logout' route.
$this->post(routeLogout()); // <- Here, where the error occurs
return $this;
}
我的App/Models/Usuario.php
模特:
namespace App\Models;
use Illuminate\Notifications\Notifiable;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Webpatser\Uuid\Uuid;
use Spatie\Activitylog\Traits\LogsActivity;
class Usuario extends Authenticatable
{
use LogsActivity, Notifiable, SoftDeletes;
protected $table = 'usuario';
protected $fillable = [/*...*/] ; // I remove this to post here on SO
protected static $logFillable = true;
public $timestamps = true;
protected $dates = [
'created_at',
'updated_at',
'deleted_at'
];
protected static function boot()
{
// Handle the \LogsActivity boot method
parent::boot();
static::saving(function ($usuario){
$usuario->uuid = Uuid::generate()->string;
});
}
public function getRouteKeyName()
{
return 'uuid';
}
}
我的 config/activitylog.php
文件:
return [
'enabled' => env('ACTIVITY_LOGGER_ENABLED', true),
'delete_records_older_than_days' => 365,
'default_log_name' => 'default',
'default_auth_driver' => null,
'subject_returns_soft_deleted_models' => false,
'activity_model' => \Spatie\Activitylog\Models\Activity::class,
];
我的 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="false"
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="API_DEBUG" value="true"/>
<env name="memory_limit" value="512M"/>
<env name="APP_DATABASE" value="test"/>
</php>
</phpunit>
我的 create_activity_log_migration
文件:
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateActivityLogTable extends Migration
{
/**
* Run the migrations.
*/
public function up()
{
Schema::create('activity_log', function (Blueprint $table) {
$table->increments('id');
$table->string('log_name')->nullable();
$table->string('description');
$table->integer('subject_id')->nullable();
$table->string('subject_type')->nullable();
$table->integer('causer_id')->nullable();
$table->string('causer_type')->nullable();
$table->text('properties')->nullable();
$table->timestamps();
$table->index('log_name');
});
}
/**
* Reverse the migrations.
*/
public function down()
{
Schema::drop('activity_log');
}
}
我注意到当我禁用 Activity 模型日志时,它工作正常。而且,当我通过 tinker 或浏览器使用该系统时,日志也同样有效。
我无法重现错误,但我确实有一些考虑:
- 您说当您 post 到注销路由时会触发错误,但这不应该触发 activity 记录器,对吧?我的意思是,那里没有触发
created
、updated
或 deleted
事件。
- 相反,当您使用工厂创建用户时,确实会触发
created
事件。这反过来会触发 activity 日志。
- 当记录器尝试创建新的
Activity
时,您会收到异常 Illuminate\Database\Eloquent\JsonEncodingException: Unable to encode attribute [properties] for model [Spatie\Activitylog\Models\Activity] to JSON: Type is not supported.
。这几乎肯定是在 Illuminate\Database\Eloquent\Concerns\HasAttributes@castAttributeAsJson
方法中抛出的,该方法对属性值执行简单的 json_encode
。
- 那么,资源是否有可能成为要记录的
properties
的一部分?在创建用户后尝试 dd($user->attributeValuesToBeLogged('created'))
。
我找到了答案(但我不知道这是否是解决此问题的最佳方法);
只需将 $this->createApplication();
放入 SetUp
方法中,在 TestCase.php
文件中,错误就会消失。
谢谢大家,伙计们。
我正在 laravel 中为我的模型编写一些测试,当我使用 spatie/laravel-activitylog.
启用 Activity 日志时遇到了一些麻烦所以,我创建了一个用户,使用 Factory
,我在系统中进行了身份验证,当我尝试注销时,我得到了这个错误:
1) Tests\Feature\Usuario\CriarUsuarioTest::testAcessaPaginaDeRegistro Illuminate\Database\Eloquent\JsonEncodingException: Unable to encode attribute [properties] for model [Spatie\Activitylog\Models\Activity] to JSON: Type is not supported.
我的测试TestCase.php
:
protected function setUp()
{
parent::setUp();
$this->user = create('App\Models\Usuario');
$this->singIn($this->user)
->disableExceptionHandling();
}
...
...
...
protected function singIn($user)
{
$this->actingAs($user);
return $this;
}
protected function singOut()
{
// routeLogout() goes to '/logout' route.
$this->post(routeLogout()); // <- Here, where the error occurs
return $this;
}
我的App/Models/Usuario.php
模特:
namespace App\Models;
use Illuminate\Notifications\Notifiable;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Webpatser\Uuid\Uuid;
use Spatie\Activitylog\Traits\LogsActivity;
class Usuario extends Authenticatable
{
use LogsActivity, Notifiable, SoftDeletes;
protected $table = 'usuario';
protected $fillable = [/*...*/] ; // I remove this to post here on SO
protected static $logFillable = true;
public $timestamps = true;
protected $dates = [
'created_at',
'updated_at',
'deleted_at'
];
protected static function boot()
{
// Handle the \LogsActivity boot method
parent::boot();
static::saving(function ($usuario){
$usuario->uuid = Uuid::generate()->string;
});
}
public function getRouteKeyName()
{
return 'uuid';
}
}
我的 config/activitylog.php
文件:
return [
'enabled' => env('ACTIVITY_LOGGER_ENABLED', true),
'delete_records_older_than_days' => 365,
'default_log_name' => 'default',
'default_auth_driver' => null,
'subject_returns_soft_deleted_models' => false,
'activity_model' => \Spatie\Activitylog\Models\Activity::class,
];
我的 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="false"
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="API_DEBUG" value="true"/>
<env name="memory_limit" value="512M"/>
<env name="APP_DATABASE" value="test"/>
</php>
</phpunit>
我的 create_activity_log_migration
文件:
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateActivityLogTable extends Migration
{
/**
* Run the migrations.
*/
public function up()
{
Schema::create('activity_log', function (Blueprint $table) {
$table->increments('id');
$table->string('log_name')->nullable();
$table->string('description');
$table->integer('subject_id')->nullable();
$table->string('subject_type')->nullable();
$table->integer('causer_id')->nullable();
$table->string('causer_type')->nullable();
$table->text('properties')->nullable();
$table->timestamps();
$table->index('log_name');
});
}
/**
* Reverse the migrations.
*/
public function down()
{
Schema::drop('activity_log');
}
}
我注意到当我禁用 Activity 模型日志时,它工作正常。而且,当我通过 tinker 或浏览器使用该系统时,日志也同样有效。
我无法重现错误,但我确实有一些考虑:
- 您说当您 post 到注销路由时会触发错误,但这不应该触发 activity 记录器,对吧?我的意思是,那里没有触发
created
、updated
或deleted
事件。 - 相反,当您使用工厂创建用户时,确实会触发
created
事件。这反过来会触发 activity 日志。 - 当记录器尝试创建新的
Activity
时,您会收到异常Illuminate\Database\Eloquent\JsonEncodingException: Unable to encode attribute [properties] for model [Spatie\Activitylog\Models\Activity] to JSON: Type is not supported.
。这几乎肯定是在Illuminate\Database\Eloquent\Concerns\HasAttributes@castAttributeAsJson
方法中抛出的,该方法对属性值执行简单的json_encode
。 - 那么,资源是否有可能成为要记录的
properties
的一部分?在创建用户后尝试dd($user->attributeValuesToBeLogged('created'))
。
我找到了答案(但我不知道这是否是解决此问题的最佳方法);
只需将 $this->createApplication();
放入 SetUp
方法中,在 TestCase.php
文件中,错误就会消失。
谢谢大家,伙计们。