156 lines
4.6 KiB
PHP
156 lines
4.6 KiB
PHP
<?php
|
||
|
||
/**
|
||
* 文件功能:AI小班长聊天控制器测试
|
||
*
|
||
* 覆盖 AI 开关、普通回复、金币福利以及上下文清理逻辑,
|
||
* 同时验证金币福利发放时不会自动动用 AI 的银行存款。
|
||
*/
|
||
|
||
namespace Tests\Feature;
|
||
|
||
use App\Models\Sysparam;
|
||
use App\Models\User;
|
||
use App\Services\AiChatService;
|
||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||
use Illuminate\Support\Facades\Redis;
|
||
use Mockery\MockInterface;
|
||
use Tests\TestCase;
|
||
|
||
/**
|
||
* 验证 AI小班长对话与金币福利接口行为。
|
||
*/
|
||
class ChatBotControllerTest extends TestCase
|
||
{
|
||
use RefreshDatabase;
|
||
|
||
/**
|
||
* 每个测试结束后清空 Redis,避免每日奖励计数彼此污染。
|
||
*/
|
||
protected function tearDown(): void
|
||
{
|
||
Redis::flushall();
|
||
parent::tearDown();
|
||
}
|
||
|
||
/**
|
||
* 默认情况下,AI 功能关闭时应直接拒绝聊天请求。
|
||
*/
|
||
public function test_chatbot_disabled_by_default(): void
|
||
{
|
||
$user = User::factory()->create();
|
||
|
||
$response = $this->actingAs($user)->postJson(route('chatbot.chat'), [
|
||
'message' => 'Hello',
|
||
'room_id' => 1,
|
||
]);
|
||
|
||
$response->assertStatus(403);
|
||
$response->assertJson(['status' => 'error']);
|
||
}
|
||
|
||
/**
|
||
* AI 功能开启后,控制器会返回模型生成的正常回复。
|
||
*/
|
||
public function test_chatbot_can_reply(): void
|
||
{
|
||
$user = User::factory()->create();
|
||
|
||
Sysparam::updateOrCreate(['alias' => 'chatbot_enabled'], ['body' => '1']);
|
||
|
||
User::factory()->create([
|
||
'username' => 'AI小班长',
|
||
'exp_num' => 0,
|
||
'jjb' => 0,
|
||
]);
|
||
|
||
// Mock the AiChatService
|
||
$this->mock(AiChatService::class, function (MockInterface $mock) {
|
||
$mock->shouldReceive('chat')
|
||
->once()
|
||
->andReturn([
|
||
'reply' => 'Hello from AI',
|
||
'provider' => 'test_provider',
|
||
'model' => 'test_model',
|
||
]);
|
||
});
|
||
|
||
$response = $this->actingAs($user)->postJson(route('chatbot.chat'), [
|
||
'message' => 'Hello',
|
||
'room_id' => 1,
|
||
]);
|
||
|
||
$response->assertStatus(200);
|
||
$response->assertJson([
|
||
'status' => 'success',
|
||
'reply' => 'Hello from AI',
|
||
'provider' => 'test_provider',
|
||
]);
|
||
}
|
||
|
||
/**
|
||
* 发放金币福利时,只使用 AI 当前手上金币,不会为了凑金额自动动用银行存款。
|
||
*/
|
||
public function test_chatbot_can_give_gold(): void
|
||
{
|
||
$user = User::factory()->create(['jjb' => 0]);
|
||
|
||
Sysparam::updateOrCreate(['alias' => 'chatbot_enabled'], ['body' => '1']);
|
||
Sysparam::updateOrCreate(['alias' => 'chatbot_max_daily_rewards'], ['body' => '1']);
|
||
Sysparam::updateOrCreate(['alias' => 'chatbot_max_gold'], ['body' => '500']);
|
||
|
||
User::factory()->create([
|
||
'username' => 'AI小班长',
|
||
'exp_num' => 0,
|
||
'jjb' => 1000000,
|
||
'bank_jjb' => 1000,
|
||
]);
|
||
|
||
// Mock the AiChatService
|
||
$this->mock(AiChatService::class, function (MockInterface $mock) {
|
||
$mock->shouldReceive('chat')
|
||
->once()
|
||
->andReturn([
|
||
'reply' => 'Here is some gold! [ACTION:GIVE_GOLD]',
|
||
'provider' => 'test_provider',
|
||
'model' => 'test_model',
|
||
]);
|
||
});
|
||
|
||
$response = $this->actingAs($user)->postJson(route('chatbot.chat'), [
|
||
'message' => 'Give me gold',
|
||
'room_id' => 1,
|
||
]);
|
||
|
||
$response->assertStatus(200);
|
||
|
||
// User should have received gold
|
||
$user->refresh();
|
||
$this->assertGreaterThan(0, $user->jjb);
|
||
$this->assertLessThanOrEqual(500, $user->jjb);
|
||
|
||
$aiUser = User::query()->where('username', 'AI小班长')->firstOrFail();
|
||
$this->assertLessThan(1000000, (int) $aiUser->jjb);
|
||
$this->assertSame(1000, (int) $aiUser->bank_jjb);
|
||
}
|
||
|
||
/**
|
||
* 用户主动清空上下文时,应调用 AI 服务清理其上下文缓存。
|
||
*/
|
||
public function test_clear_context(): void
|
||
{
|
||
$user = User::factory()->create();
|
||
|
||
$this->mock(AiChatService::class, function (MockInterface $mock) use ($user) {
|
||
$mock->shouldReceive('clearContext')
|
||
->once()
|
||
->with($user->id);
|
||
});
|
||
|
||
$response = $this->actingAs($user)->postJson(route('chatbot.clear'));
|
||
|
||
$response->assertStatus(200);
|
||
$response->assertJson(['status' => 'success']);
|
||
}
|
||
}
|