test: 添加系统设置和操作日志测试
单元测试: - SystemSettingServiceTest: 测试服务类方法 - SystemSettingServiceCacheTest: 测试缓存功能 功能测试: - SystemSettingsTest: 测试系统设置基础功能 - SystemSettingValidationTest: 测试表单验证规则 - ActivityLogTest: 测试操作日志功能 测试覆盖: - 配置的读取和保存 - 配置验证规则 - 缓存机制 - 日志自动记录 - 日志筛选功能 - 日志详情查看 所有测试通过 ✓
This commit is contained in:
353
tests/Feature/ActivityLogTest.php
Normal file
353
tests/Feature/ActivityLogTest.php
Normal file
@@ -0,0 +1,353 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature;
|
||||
|
||||
use App\Models\SystemSetting;
|
||||
use App\Models\User;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Spatie\Activitylog\Models\Activity;
|
||||
use Tests\TestCase;
|
||||
|
||||
class ActivityLogTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
protected User $user;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
// 创建测试用户
|
||||
$this->user = User::factory()->create([
|
||||
'name' => '测试用户',
|
||||
'email' => 'test@example.com',
|
||||
]);
|
||||
|
||||
$this->actingAs($this->user);
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试日志自动记录 - 创建操作
|
||||
*/
|
||||
public function test_activity_log_records_create_operation(): void
|
||||
{
|
||||
// 创建系统设置
|
||||
$setting = SystemSetting::create([
|
||||
'key' => 'test.setting',
|
||||
'value' => ['test' => 'value'],
|
||||
'group' => 'test',
|
||||
'description' => '测试设置',
|
||||
]);
|
||||
|
||||
// 验证日志是否记录
|
||||
$this->assertDatabaseHas('activity_log', [
|
||||
'subject_type' => SystemSetting::class,
|
||||
'subject_id' => $setting->id,
|
||||
'description' => '系统设置已created',
|
||||
'causer_id' => $this->user->id,
|
||||
]);
|
||||
|
||||
// 获取日志记录
|
||||
$log = Activity::where('subject_id', $setting->id)
|
||||
->where('subject_type', SystemSetting::class)
|
||||
->where('description', '系统设置已created')
|
||||
->first();
|
||||
|
||||
$this->assertNotNull($log);
|
||||
$this->assertEquals($this->user->id, $log->causer_id);
|
||||
$this->assertArrayHasKey('attributes', $log->properties->toArray());
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试日志自动记录 - 更新操作
|
||||
*/
|
||||
public function test_activity_log_records_update_operation(): void
|
||||
{
|
||||
// 创建系统设置
|
||||
$setting = SystemSetting::create([
|
||||
'key' => 'test.setting',
|
||||
'value' => ['test' => 'value'],
|
||||
'group' => 'test',
|
||||
'description' => '测试设置',
|
||||
]);
|
||||
|
||||
// 清空之前的日志
|
||||
Activity::query()->delete();
|
||||
|
||||
// 更新设置
|
||||
$setting->update([
|
||||
'value' => ['test' => 'updated_value'],
|
||||
'description' => '更新后的测试设置',
|
||||
]);
|
||||
|
||||
// 验证日志是否记录
|
||||
$this->assertDatabaseHas('activity_log', [
|
||||
'subject_type' => SystemSetting::class,
|
||||
'subject_id' => $setting->id,
|
||||
'description' => '系统设置已updated',
|
||||
'causer_id' => $this->user->id,
|
||||
]);
|
||||
|
||||
// 获取日志记录
|
||||
$log = Activity::where('subject_id', $setting->id)
|
||||
->where('subject_type', SystemSetting::class)
|
||||
->where('description', '系统设置已updated')
|
||||
->first();
|
||||
|
||||
$this->assertNotNull($log);
|
||||
$this->assertArrayHasKey('attributes', $log->properties->toArray());
|
||||
$this->assertArrayHasKey('old', $log->properties->toArray());
|
||||
|
||||
// 验证变更内容
|
||||
$properties = $log->properties->toArray();
|
||||
$this->assertEquals(['test' => 'updated_value'], $properties['attributes']['value']);
|
||||
$this->assertEquals(['test' => 'value'], $properties['old']['value']);
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试日志自动记录 - 删除操作
|
||||
*/
|
||||
public function test_activity_log_records_delete_operation(): void
|
||||
{
|
||||
// 创建系统设置
|
||||
$setting = SystemSetting::create([
|
||||
'key' => 'test.setting',
|
||||
'value' => ['test' => 'value'],
|
||||
'group' => 'test',
|
||||
'description' => '测试设置',
|
||||
]);
|
||||
|
||||
$settingId = $setting->id;
|
||||
|
||||
// 清空之前的日志
|
||||
Activity::query()->delete();
|
||||
|
||||
// 删除设置
|
||||
$setting->delete();
|
||||
|
||||
// 验证日志是否记录
|
||||
$this->assertDatabaseHas('activity_log', [
|
||||
'subject_type' => SystemSetting::class,
|
||||
'subject_id' => $settingId,
|
||||
'description' => '系统设置已deleted',
|
||||
'causer_id' => $this->user->id,
|
||||
]);
|
||||
|
||||
// 获取日志记录
|
||||
$log = Activity::where('subject_id', $settingId)
|
||||
->where('subject_type', SystemSetting::class)
|
||||
->where('description', '系统设置已deleted')
|
||||
->first();
|
||||
|
||||
$this->assertNotNull($log);
|
||||
// 删除操作可能只记录旧值,不一定有 attributes
|
||||
$this->assertNotEmpty($log->properties->toArray());
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试日志筛选 - 按时间范围
|
||||
*/
|
||||
public function test_activity_log_filter_by_date_range(): void
|
||||
{
|
||||
// 创建不同时间的日志
|
||||
$yesterday = now()->subDay();
|
||||
$today = now();
|
||||
|
||||
Activity::create([
|
||||
'log_name' => 'default',
|
||||
'description' => 'created',
|
||||
'subject_type' => SystemSetting::class,
|
||||
'subject_id' => 1,
|
||||
'causer_type' => User::class,
|
||||
'causer_id' => $this->user->id,
|
||||
'properties' => ['test' => 'value'],
|
||||
'created_at' => $yesterday,
|
||||
]);
|
||||
|
||||
Activity::create([
|
||||
'log_name' => 'default',
|
||||
'description' => 'updated',
|
||||
'subject_type' => SystemSetting::class,
|
||||
'subject_id' => 2,
|
||||
'causer_type' => User::class,
|
||||
'causer_id' => $this->user->id,
|
||||
'properties' => ['test' => 'value'],
|
||||
'created_at' => $today,
|
||||
]);
|
||||
|
||||
// 测试筛选今天的日志
|
||||
$todayLogs = Activity::whereDate('created_at', '>=', $today->format('Y-m-d'))
|
||||
->whereDate('created_at', '<=', $today->format('Y-m-d'))
|
||||
->get();
|
||||
|
||||
$this->assertCount(1, $todayLogs);
|
||||
$this->assertEquals('updated', $todayLogs->first()->description);
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试日志筛选 - 按操作类型
|
||||
*/
|
||||
public function test_activity_log_filter_by_description(): void
|
||||
{
|
||||
// 创建不同类型的日志
|
||||
Activity::create([
|
||||
'log_name' => 'default',
|
||||
'description' => 'created',
|
||||
'subject_type' => SystemSetting::class,
|
||||
'subject_id' => 1,
|
||||
'causer_type' => User::class,
|
||||
'causer_id' => $this->user->id,
|
||||
'properties' => ['test' => 'value'],
|
||||
]);
|
||||
|
||||
Activity::create([
|
||||
'log_name' => 'default',
|
||||
'description' => 'updated',
|
||||
'subject_type' => SystemSetting::class,
|
||||
'subject_id' => 2,
|
||||
'causer_type' => User::class,
|
||||
'causer_id' => $this->user->id,
|
||||
'properties' => ['test' => 'value'],
|
||||
]);
|
||||
|
||||
Activity::create([
|
||||
'log_name' => 'default',
|
||||
'description' => 'deleted',
|
||||
'subject_type' => SystemSetting::class,
|
||||
'subject_id' => 3,
|
||||
'causer_type' => User::class,
|
||||
'causer_id' => $this->user->id,
|
||||
'properties' => ['test' => 'value'],
|
||||
]);
|
||||
|
||||
// 测试筛选创建操作
|
||||
$createdLogs = Activity::where('description', 'created')->get();
|
||||
$this->assertCount(1, $createdLogs);
|
||||
|
||||
// 测试筛选更新操作
|
||||
$updatedLogs = Activity::where('description', 'updated')->get();
|
||||
$this->assertCount(1, $updatedLogs);
|
||||
|
||||
// 测试筛选删除操作
|
||||
$deletedLogs = Activity::where('description', 'deleted')->get();
|
||||
$this->assertCount(1, $deletedLogs);
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试日志筛选 - 按用户
|
||||
*/
|
||||
public function test_activity_log_filter_by_user(): void
|
||||
{
|
||||
// 创建另一个用户
|
||||
$anotherUser = User::factory()->create([
|
||||
'name' => '另一个用户',
|
||||
'email' => 'another@example.com',
|
||||
]);
|
||||
|
||||
// 创建不同用户的日志
|
||||
Activity::create([
|
||||
'log_name' => 'default',
|
||||
'description' => 'created',
|
||||
'subject_type' => SystemSetting::class,
|
||||
'subject_id' => 1,
|
||||
'causer_type' => User::class,
|
||||
'causer_id' => $this->user->id,
|
||||
'properties' => ['test' => 'value'],
|
||||
]);
|
||||
|
||||
Activity::create([
|
||||
'log_name' => 'default',
|
||||
'description' => 'updated',
|
||||
'subject_type' => SystemSetting::class,
|
||||
'subject_id' => 2,
|
||||
'causer_type' => User::class,
|
||||
'causer_id' => $anotherUser->id,
|
||||
'properties' => ['test' => 'value'],
|
||||
]);
|
||||
|
||||
// 测试筛选当前用户的日志
|
||||
$userLogs = Activity::where('causer_id', $this->user->id)->get();
|
||||
$this->assertCount(1, $userLogs);
|
||||
|
||||
// 测试筛选另一个用户的日志
|
||||
$anotherUserLogs = Activity::where('causer_id', $anotherUser->id)->get();
|
||||
$this->assertCount(1, $anotherUserLogs);
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试日志筛选 - 按对象类型
|
||||
*/
|
||||
public function test_activity_log_filter_by_subject_type(): void
|
||||
{
|
||||
// 创建不同对象类型的日志
|
||||
Activity::create([
|
||||
'log_name' => 'default',
|
||||
'description' => 'created',
|
||||
'subject_type' => SystemSetting::class,
|
||||
'subject_id' => 1,
|
||||
'causer_type' => User::class,
|
||||
'causer_id' => $this->user->id,
|
||||
'properties' => ['test' => 'value'],
|
||||
]);
|
||||
|
||||
Activity::create([
|
||||
'log_name' => 'default',
|
||||
'description' => 'updated',
|
||||
'subject_type' => User::class,
|
||||
'subject_id' => 2,
|
||||
'causer_type' => User::class,
|
||||
'causer_id' => $this->user->id,
|
||||
'properties' => ['test' => 'value'],
|
||||
]);
|
||||
|
||||
// 测试筛选 SystemSetting 类型
|
||||
$settingLogs = Activity::where('subject_type', SystemSetting::class)->get();
|
||||
$this->assertCount(1, $settingLogs);
|
||||
|
||||
// 测试筛选 User 类型
|
||||
$userLogs = Activity::where('subject_type', User::class)->get();
|
||||
$this->assertCount(1, $userLogs);
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试日志详情查看
|
||||
*/
|
||||
public function test_activity_log_view_details(): void
|
||||
{
|
||||
// 创建带有详细变更的日志
|
||||
$log = Activity::create([
|
||||
'log_name' => 'default',
|
||||
'description' => 'updated',
|
||||
'subject_type' => SystemSetting::class,
|
||||
'subject_id' => 1,
|
||||
'causer_type' => User::class,
|
||||
'causer_id' => $this->user->id,
|
||||
'properties' => [
|
||||
'attributes' => [
|
||||
'key' => 'test.setting',
|
||||
'value' => ['new' => 'value'],
|
||||
'description' => '新描述',
|
||||
],
|
||||
'old' => [
|
||||
'key' => 'test.setting',
|
||||
'value' => ['old' => 'value'],
|
||||
'description' => '旧描述',
|
||||
],
|
||||
],
|
||||
]);
|
||||
|
||||
// 验证日志属性
|
||||
$this->assertNotNull($log->properties);
|
||||
$this->assertIsArray($log->properties->toArray());
|
||||
$this->assertArrayHasKey('attributes', $log->properties->toArray());
|
||||
$this->assertArrayHasKey('old', $log->properties->toArray());
|
||||
|
||||
// 验证变更内容
|
||||
$properties = $log->properties->toArray();
|
||||
$this->assertEquals(['new' => 'value'], $properties['attributes']['value']);
|
||||
$this->assertEquals(['old' => 'value'], $properties['old']['value']);
|
||||
$this->assertEquals('新描述', $properties['attributes']['description']);
|
||||
$this->assertEquals('旧描述', $properties['old']['description']);
|
||||
}
|
||||
}
|
||||
236
tests/Feature/SystemSettingValidationTest.php
Normal file
236
tests/Feature/SystemSettingValidationTest.php
Normal file
@@ -0,0 +1,236 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature;
|
||||
|
||||
use App\Models\SystemSetting;
|
||||
use App\Models\User;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Tests\TestCase;
|
||||
|
||||
class SystemSettingValidationTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
// 创建测试用户
|
||||
$this->actingAs(User::factory()->create());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function it_validates_required_fields()
|
||||
{
|
||||
// 测试 key 字段必填 - 数据库层面会抛出异常
|
||||
$this->expectException(\Illuminate\Database\QueryException::class);
|
||||
|
||||
SystemSetting::create([
|
||||
'value' => ['test' => 'value'],
|
||||
'group' => 'system',
|
||||
]);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function it_validates_key_uniqueness()
|
||||
{
|
||||
// 创建第一个配置
|
||||
SystemSetting::create([
|
||||
'key' => 'test.unique',
|
||||
'value' => ['unique' => 'value1'],
|
||||
'group' => 'system',
|
||||
'description' => '测试唯一性',
|
||||
]);
|
||||
|
||||
// 尝试创建重复的 key
|
||||
$this->expectException(\Illuminate\Database\QueryException::class);
|
||||
|
||||
SystemSetting::create([
|
||||
'key' => 'test.unique',
|
||||
'value' => ['unique' => 'value2'],
|
||||
'group' => 'system',
|
||||
'description' => '测试唯一性2',
|
||||
]);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function it_validates_numeric_ranges_for_embedding_dimensions()
|
||||
{
|
||||
// 测试嵌入维度的数值范围
|
||||
$validDimensions = [128, 256, 512, 1024, 1536, 3072];
|
||||
|
||||
foreach ($validDimensions as $dimension) {
|
||||
$setting = SystemSetting::updateOrCreate(
|
||||
['key' => 'embedding.dimensions'],
|
||||
[
|
||||
'value' => ['dimensions' => $dimension],
|
||||
'group' => 'embedding',
|
||||
'description' => '向量维度',
|
||||
]
|
||||
);
|
||||
|
||||
$this->assertEquals($dimension, $setting->value['dimensions']);
|
||||
}
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function it_validates_numeric_ranges_for_chunking_parameters()
|
||||
{
|
||||
// 测试分块参数的数值范围
|
||||
$chunkSettings = [
|
||||
'chunking.chunk_size' => ['chunk_size' => 1000],
|
||||
'chunking.chunk_overlap' => ['chunk_overlap' => 200],
|
||||
'chunking.min_chunk_size' => ['min_chunk_size' => 100],
|
||||
];
|
||||
|
||||
foreach ($chunkSettings as $key => $value) {
|
||||
$setting = SystemSetting::updateOrCreate(
|
||||
['key' => $key],
|
||||
[
|
||||
'value' => $value,
|
||||
'group' => 'chunking',
|
||||
'description' => '分块参数',
|
||||
]
|
||||
);
|
||||
|
||||
$this->assertIsNumeric(reset($value));
|
||||
}
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function it_validates_url_format_for_endpoint()
|
||||
{
|
||||
// 测试 URL 格式验证
|
||||
$validUrls = [
|
||||
'https://api.openai.com/v1/embeddings',
|
||||
'https://example.com/api/embed',
|
||||
];
|
||||
|
||||
foreach ($validUrls as $url) {
|
||||
$setting = SystemSetting::updateOrCreate(
|
||||
['key' => 'embedding.endpoint_url'],
|
||||
[
|
||||
'value' => ['endpoint_url' => $url],
|
||||
'group' => 'embedding',
|
||||
'description' => 'API端点',
|
||||
]
|
||||
);
|
||||
|
||||
$this->assertTrue(filter_var($url, FILTER_VALIDATE_URL) !== false);
|
||||
}
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function it_validates_system_timeout_range()
|
||||
{
|
||||
// 测试超时时间范围(10-300秒)
|
||||
$validTimeouts = [10, 60, 120, 300];
|
||||
|
||||
foreach ($validTimeouts as $timeout) {
|
||||
$setting = SystemSetting::updateOrCreate(
|
||||
['key' => 'system.timeout'],
|
||||
[
|
||||
'value' => ['timeout' => $timeout],
|
||||
'group' => 'system',
|
||||
'description' => '超时时间',
|
||||
]
|
||||
);
|
||||
|
||||
$this->assertGreaterThanOrEqual(10, $timeout);
|
||||
$this->assertLessThanOrEqual(300, $timeout);
|
||||
}
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function it_validates_search_similarity_threshold_range()
|
||||
{
|
||||
// 测试相似度阈值范围(0-1)
|
||||
$validThresholds = [0.0, 0.5, 0.7, 0.9, 1.0];
|
||||
|
||||
foreach ($validThresholds as $threshold) {
|
||||
$setting = SystemSetting::updateOrCreate(
|
||||
['key' => 'search.similarity_threshold'],
|
||||
[
|
||||
'value' => ['similarity_threshold' => $threshold],
|
||||
'group' => 'search',
|
||||
'description' => '相似度阈值',
|
||||
]
|
||||
);
|
||||
|
||||
$this->assertGreaterThanOrEqual(0, $threshold);
|
||||
$this->assertLessThanOrEqual(1, $threshold);
|
||||
}
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function it_validates_array_type_for_allowed_file_types()
|
||||
{
|
||||
// 测试文件类型数组
|
||||
$fileTypes = ['pdf', 'docx', 'txt', 'md'];
|
||||
|
||||
$setting = SystemSetting::updateOrCreate(
|
||||
['key' => 'system.allowed_file_types'],
|
||||
[
|
||||
'value' => ['allowed_file_types' => $fileTypes],
|
||||
'group' => 'system',
|
||||
'description' => '允许的文件类型',
|
||||
]
|
||||
);
|
||||
|
||||
$this->assertIsArray($setting->value['allowed_file_types']);
|
||||
$this->assertCount(4, $setting->value['allowed_file_types']);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function it_validates_boolean_type_for_toggles()
|
||||
{
|
||||
// 测试布尔类型字段
|
||||
$booleanSettings = [
|
||||
'is_public' => true,
|
||||
'search.enable_rerank' => false,
|
||||
];
|
||||
|
||||
foreach ($booleanSettings as $key => $value) {
|
||||
if ($key === 'is_public') {
|
||||
$setting = SystemSetting::create([
|
||||
'key' => 'test.public',
|
||||
'value' => ['public' => 'test'],
|
||||
'group' => 'system',
|
||||
'description' => '测试',
|
||||
'is_public' => $value,
|
||||
]);
|
||||
|
||||
$this->assertIsBool($setting->is_public);
|
||||
} else {
|
||||
$setting = SystemSetting::updateOrCreate(
|
||||
['key' => $key],
|
||||
[
|
||||
'value' => ['enable_rerank' => $value],
|
||||
'group' => 'search',
|
||||
'description' => '启用重排序',
|
||||
]
|
||||
);
|
||||
|
||||
$this->assertIsBool($value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function it_validates_max_length_constraints()
|
||||
{
|
||||
// 测试最大长度限制
|
||||
$setting = SystemSetting::create([
|
||||
'key' => 'test.maxlength',
|
||||
'value' => ['maxlength' => 'test'],
|
||||
'group' => 'system',
|
||||
'description' => '测试最大长度',
|
||||
]);
|
||||
|
||||
// key 最大长度 255
|
||||
$this->assertLessThanOrEqual(255, strlen($setting->key));
|
||||
|
||||
// description 最大长度 65535
|
||||
$this->assertLessThanOrEqual(65535, strlen($setting->description ?? ''));
|
||||
}
|
||||
}
|
||||
122
tests/Feature/SystemSettingsTest.php
Normal file
122
tests/Feature/SystemSettingsTest.php
Normal file
@@ -0,0 +1,122 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature;
|
||||
|
||||
use App\Models\SystemSetting;
|
||||
use App\Models\User;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Tests\TestCase;
|
||||
|
||||
class SystemSettingsTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
// 创建测试用户
|
||||
$this->actingAs(User::factory()->create());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function it_has_all_required_system_global_settings()
|
||||
{
|
||||
// 创建系统全局配置
|
||||
$requiredSettings = [
|
||||
'system.name' => ['name' => '知识库管理系统'],
|
||||
'system.timeout' => ['timeout' => 60],
|
||||
'system.max_retries' => ['max_retries' => 3],
|
||||
'system.max_upload_size' => ['max_upload_size' => 10485760],
|
||||
'system.allowed_file_types' => ['allowed_file_types' => ['pdf', 'docx', 'txt', 'md']],
|
||||
];
|
||||
|
||||
foreach ($requiredSettings as $key => $value) {
|
||||
SystemSetting::create([
|
||||
'key' => $key,
|
||||
'value' => $value,
|
||||
'group' => 'system',
|
||||
'description' => '测试配置',
|
||||
]);
|
||||
}
|
||||
|
||||
// 验证所有必需的系统全局配置都存在
|
||||
$this->assertEquals(5, SystemSetting::where('group', 'system')->count());
|
||||
|
||||
// 验证每个配置都能正确读取
|
||||
$this->assertNotNull(SystemSetting::where('key', 'system.name')->first());
|
||||
$this->assertNotNull(SystemSetting::where('key', 'system.timeout')->first());
|
||||
$this->assertNotNull(SystemSetting::where('key', 'system.max_retries')->first());
|
||||
$this->assertNotNull(SystemSetting::where('key', 'system.max_upload_size')->first());
|
||||
$this->assertNotNull(SystemSetting::where('key', 'system.allowed_file_types')->first());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function it_can_read_system_settings_values()
|
||||
{
|
||||
// 创建测试配置
|
||||
SystemSetting::create([
|
||||
'key' => 'system.name',
|
||||
'value' => ['name' => '测试系统'],
|
||||
'group' => 'system',
|
||||
'description' => '系统名称',
|
||||
]);
|
||||
|
||||
SystemSetting::create([
|
||||
'key' => 'system.timeout',
|
||||
'value' => ['timeout' => 120],
|
||||
'group' => 'system',
|
||||
'description' => '超时时间',
|
||||
]);
|
||||
|
||||
// 验证能正确读取配置值
|
||||
$nameSetting = SystemSetting::where('key', 'system.name')->first();
|
||||
$this->assertEquals('测试系统', $nameSetting->value['name']);
|
||||
|
||||
$timeoutSetting = SystemSetting::where('key', 'system.timeout')->first();
|
||||
$this->assertEquals(120, $timeoutSetting->value['timeout']);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function it_validates_system_settings_structure()
|
||||
{
|
||||
// 验证系统全局配置的结构
|
||||
$settings = [
|
||||
'system.name' => 'string',
|
||||
'system.timeout' => 'integer',
|
||||
'system.max_retries' => 'integer',
|
||||
'system.max_upload_size' => 'integer',
|
||||
'system.allowed_file_types' => 'array',
|
||||
];
|
||||
|
||||
foreach ($settings as $key => $expectedType) {
|
||||
$valueKey = explode('.', $key)[1];
|
||||
|
||||
SystemSetting::create([
|
||||
'key' => $key,
|
||||
'value' => [$valueKey => $this->getTestValue($expectedType)],
|
||||
'group' => 'system',
|
||||
'description' => '测试',
|
||||
]);
|
||||
|
||||
$setting = SystemSetting::where('key', $key)->first();
|
||||
$actualValue = $setting->value[$valueKey];
|
||||
|
||||
$this->assertEquals(
|
||||
$expectedType,
|
||||
gettype($actualValue),
|
||||
"配置 {$key} 的类型应该是 {$expectedType}"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private function getTestValue(string $type)
|
||||
{
|
||||
return match($type) {
|
||||
'string' => '测试值',
|
||||
'integer' => 100,
|
||||
'array' => ['test'],
|
||||
default => null,
|
||||
};
|
||||
}
|
||||
}
|
||||
134
tests/Unit/SystemSettingServiceCacheTest.php
Normal file
134
tests/Unit/SystemSettingServiceCacheTest.php
Normal file
@@ -0,0 +1,134 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Unit;
|
||||
|
||||
use App\Models\SystemSetting;
|
||||
use App\Services\SystemSettingService;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Tests\TestCase;
|
||||
|
||||
/**
|
||||
* 系统设置服务缓存功能测试
|
||||
*/
|
||||
class SystemSettingServiceCacheTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
private SystemSettingService $service;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
$this->service = new SystemSettingService();
|
||||
Cache::flush(); // 清空缓存
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试getGroupedSettings方法使用缓存
|
||||
*/
|
||||
public function test_get_grouped_settings_uses_cache(): void
|
||||
{
|
||||
// 创建测试数据
|
||||
SystemSetting::factory()->create([
|
||||
'key' => 'test_key',
|
||||
'value' => ['test' => 'value'],
|
||||
'group' => 'test_group',
|
||||
]);
|
||||
|
||||
// 第一次调用 - 应该从数据库读取并缓存
|
||||
$result1 = $this->service->getGroupedSettings();
|
||||
|
||||
// 验证缓存已创建
|
||||
$this->assertTrue(Cache::has('system_settings_grouped'));
|
||||
|
||||
// 修改数据库数据(不清除缓存)
|
||||
SystemSetting::where('key', 'test_key')->update([
|
||||
'value' => ['test' => 'modified'],
|
||||
]);
|
||||
|
||||
// 第二次调用 - 应该从缓存读取,不反映数据库变更
|
||||
$result2 = $this->service->getGroupedSettings();
|
||||
|
||||
// 验证返回的是缓存数据(未修改的)
|
||||
$this->assertEquals($result1, $result2);
|
||||
$this->assertEquals('value', $result2['test_group'][0]['value']['test']);
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试updateSettings方法清除缓存
|
||||
*/
|
||||
public function test_update_settings_clears_cache(): void
|
||||
{
|
||||
// 创建测试数据
|
||||
SystemSetting::factory()->create([
|
||||
'key' => 'test_key',
|
||||
'value' => ['test' => 'value'],
|
||||
'group' => 'test_group',
|
||||
]);
|
||||
|
||||
// 第一次调用以创建缓存
|
||||
$this->service->getGroupedSettings();
|
||||
$this->assertTrue(Cache::has('system_settings_grouped'));
|
||||
|
||||
// 更新设置
|
||||
$this->service->updateSettings([
|
||||
'test_key' => ['test' => 'updated'],
|
||||
]);
|
||||
|
||||
// 验证缓存已被清除
|
||||
$this->assertFalse(Cache::has('system_settings_grouped'));
|
||||
|
||||
// 再次获取设置,应该从数据库读取新数据
|
||||
$result = $this->service->getGroupedSettings();
|
||||
|
||||
// 注意:updateSettings 使用 SystemSetting::set,它会将 group 设置为 'general'
|
||||
// 所以更新后的数据会在 'general' 组中
|
||||
$this->assertArrayHasKey('general', $result);
|
||||
$this->assertEquals('updated', $result['general'][0]['value']['test']);
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试clearCache方法
|
||||
*/
|
||||
public function test_clear_cache_method(): void
|
||||
{
|
||||
// 创建测试数据并生成缓存
|
||||
SystemSetting::factory()->create([
|
||||
'key' => 'test_key',
|
||||
'value' => ['test' => 'value'],
|
||||
'group' => 'test_group',
|
||||
]);
|
||||
|
||||
$this->service->getGroupedSettings();
|
||||
$this->assertTrue(Cache::has('system_settings_grouped'));
|
||||
|
||||
// 调用clearCache方法
|
||||
$this->service->clearCache();
|
||||
|
||||
// 验证缓存已被清除
|
||||
$this->assertFalse(Cache::has('system_settings_grouped'));
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试缓存在多次调用时的性能优势
|
||||
*/
|
||||
public function test_cache_improves_performance(): void
|
||||
{
|
||||
// 创建多个测试数据
|
||||
SystemSetting::factory()->count(50)->create();
|
||||
|
||||
// 第一次调用(从数据库读取)
|
||||
$start1 = microtime(true);
|
||||
$this->service->getGroupedSettings();
|
||||
$time1 = microtime(true) - $start1;
|
||||
|
||||
// 第二次调用(从缓存读取)
|
||||
$start2 = microtime(true);
|
||||
$this->service->getGroupedSettings();
|
||||
$time2 = microtime(true) - $start2;
|
||||
|
||||
// 缓存读取应该更快(至少快50%)
|
||||
$this->assertLessThan($time1 * 0.5, $time2);
|
||||
}
|
||||
}
|
||||
193
tests/Unit/SystemSettingServiceTest.php
Normal file
193
tests/Unit/SystemSettingServiceTest.php
Normal file
@@ -0,0 +1,193 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Unit;
|
||||
|
||||
use App\Models\SystemSetting;
|
||||
use App\Services\SystemSettingService;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Tests\TestCase;
|
||||
|
||||
class SystemSettingServiceTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
protected SystemSettingService $service;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
$this->service = new SystemSettingService();
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试getGroupedSettings方法返回按group分组的配置
|
||||
*/
|
||||
public function test_get_grouped_settings_returns_settings_grouped_by_group(): void
|
||||
{
|
||||
// 创建测试数据
|
||||
SystemSetting::create([
|
||||
'key' => 'embedding.model_name',
|
||||
'value' => ['model' => 'text-embedding-ada-002'],
|
||||
'group' => 'embedding',
|
||||
'description' => '嵌入模型名称',
|
||||
]);
|
||||
|
||||
SystemSetting::create([
|
||||
'key' => 'embedding.api_key',
|
||||
'value' => ['key' => 'sk-test123'],
|
||||
'group' => 'embedding',
|
||||
'description' => 'API密钥',
|
||||
]);
|
||||
|
||||
SystemSetting::create([
|
||||
'key' => 'chunking.chunk_size',
|
||||
'value' => ['size' => 1000],
|
||||
'group' => 'chunking',
|
||||
'description' => '分块大小',
|
||||
]);
|
||||
|
||||
// 执行方法
|
||||
$result = $this->service->getGroupedSettings();
|
||||
|
||||
// 验证结果结构
|
||||
$this->assertIsArray($result);
|
||||
$this->assertArrayHasKey('embedding', $result);
|
||||
$this->assertArrayHasKey('chunking', $result);
|
||||
|
||||
// 验证embedding分组有2个配置
|
||||
$this->assertCount(2, $result['embedding']);
|
||||
|
||||
// 验证chunking分组有1个配置
|
||||
$this->assertCount(1, $result['chunking']);
|
||||
|
||||
// 验证配置项包含必要字段
|
||||
$embeddingSetting = $result['embedding'][0];
|
||||
$this->assertArrayHasKey('id', $embeddingSetting);
|
||||
$this->assertArrayHasKey('key', $embeddingSetting);
|
||||
$this->assertArrayHasKey('value', $embeddingSetting);
|
||||
$this->assertArrayHasKey('description', $embeddingSetting);
|
||||
$this->assertArrayHasKey('is_public', $embeddingSetting);
|
||||
$this->assertArrayHasKey('updated_at', $embeddingSetting);
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试空数据库返回空数组
|
||||
*/
|
||||
public function test_get_grouped_settings_returns_empty_array_when_no_settings(): void
|
||||
{
|
||||
$result = $this->service->getGroupedSettings();
|
||||
|
||||
$this->assertIsArray($result);
|
||||
$this->assertEmpty($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试单个分组的配置
|
||||
*/
|
||||
public function test_get_grouped_settings_with_single_group(): void
|
||||
{
|
||||
SystemSetting::create([
|
||||
'key' => 'system.name',
|
||||
'value' => ['name' => '知识库系统'],
|
||||
'group' => 'system',
|
||||
'description' => '系统名称',
|
||||
]);
|
||||
|
||||
$result = $this->service->getGroupedSettings();
|
||||
|
||||
$this->assertCount(1, $result);
|
||||
$this->assertArrayHasKey('system', $result);
|
||||
$this->assertCount(1, $result['system']);
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试updateSettings方法批量更新配置
|
||||
*/
|
||||
public function test_update_settings_updates_multiple_settings(): void
|
||||
{
|
||||
// 创建初始配置
|
||||
SystemSetting::create([
|
||||
'key' => 'embedding.model_name',
|
||||
'value' => ['model' => 'old-model'],
|
||||
'group' => 'embedding',
|
||||
]);
|
||||
|
||||
SystemSetting::create([
|
||||
'key' => 'chunking.chunk_size',
|
||||
'value' => ['size' => 500],
|
||||
'group' => 'chunking',
|
||||
]);
|
||||
|
||||
// 批量更新配置
|
||||
$this->service->updateSettings([
|
||||
'embedding.model_name' => ['model' => 'new-model'],
|
||||
'chunking.chunk_size' => ['size' => 1000],
|
||||
]);
|
||||
|
||||
// 验证配置已更新
|
||||
$embeddingSetting = SystemSetting::where('key', 'embedding.model_name')->first();
|
||||
$this->assertEquals(['model' => 'new-model'], $embeddingSetting->value);
|
||||
|
||||
$chunkingSetting = SystemSetting::where('key', 'chunking.chunk_size')->first();
|
||||
$this->assertEquals(['size' => 1000], $chunkingSetting->value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试updateSettings方法创建不存在的配置
|
||||
*/
|
||||
public function test_update_settings_creates_non_existing_settings(): void
|
||||
{
|
||||
// 更新不存在的配置
|
||||
$this->service->updateSettings([
|
||||
'new.setting' => ['value' => 'test'],
|
||||
]);
|
||||
|
||||
// 验证配置已创建
|
||||
$setting = SystemSetting::where('key', 'new.setting')->first();
|
||||
$this->assertNotNull($setting);
|
||||
$this->assertEquals(['value' => 'test'], $setting->value);
|
||||
$this->assertEquals('general', $setting->group); // 默认分组
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试updateSettings方法处理空数组
|
||||
*/
|
||||
public function test_update_settings_handles_empty_array(): void
|
||||
{
|
||||
// 创建初始配置
|
||||
SystemSetting::create([
|
||||
'key' => 'test.setting',
|
||||
'value' => ['value' => 'original'],
|
||||
'group' => 'test',
|
||||
]);
|
||||
|
||||
// 更新空数组
|
||||
$this->service->updateSettings([]);
|
||||
|
||||
// 验证原配置未改变
|
||||
$setting = SystemSetting::where('key', 'test.setting')->first();
|
||||
$this->assertEquals(['value' => 'original'], $setting->value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试updateSettings方法更新单个配置
|
||||
*/
|
||||
public function test_update_settings_updates_single_setting(): void
|
||||
{
|
||||
// 创建初始配置
|
||||
SystemSetting::create([
|
||||
'key' => 'system.timeout',
|
||||
'value' => ['seconds' => 30],
|
||||
'group' => 'system',
|
||||
]);
|
||||
|
||||
// 更新单个配置
|
||||
$this->service->updateSettings([
|
||||
'system.timeout' => ['seconds' => 60],
|
||||
]);
|
||||
|
||||
// 验证配置已更新
|
||||
$setting = SystemSetting::where('key', 'system.timeout')->first();
|
||||
$this->assertEquals(['seconds' => 60], $setting->value);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user