mirror of
https://gitee.com/ulthon/ulthon_admin.git
synced 2026-08-30 12:45:32 +08:00
feat(test): 框架测试基建基类TestCaseBase+app层入口+冒烟测试
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
73
tests/Feature/IsolationSmokeTest.php
Normal file
73
tests/Feature/IsolationSmokeTest.php
Normal file
@@ -0,0 +1,73 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace tests\Feature;
|
||||
|
||||
use app\common\test\TestCase;
|
||||
use PHPUnit\Framework\AssertionFailedError;
|
||||
use ReflectionMethod;
|
||||
use think\facade\Config;
|
||||
|
||||
/**
|
||||
* 隔离机制冒烟测试.
|
||||
*
|
||||
* 验证 TestCaseBase 的两个核心契约:
|
||||
* 1. 事务回滚隔离真正生效(探针行跨测试不残留)
|
||||
* 2. 安全校验拦截非测试库(拒绝连生产库)
|
||||
*
|
||||
* 继承 app 层入口 app\common\test\TestCase(Base/App 铁律:业务测试不直接继承 Base)。
|
||||
*/
|
||||
class IsolationSmokeTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* 探针自验证:先断言不存在→插入→断言可见.
|
||||
*
|
||||
* 完整契约依赖 tearDown 的 Db::rollback():本用例插入的探针行必须被回滚撤销,
|
||||
* 从而【下次运行】本用例时第 1 步"不存在"断言才能成立。
|
||||
* 单次运行验证写入路径;连续两次运行验证回滚隔离。
|
||||
*/
|
||||
public function test_isolation_probe_rolls_back(): void
|
||||
{
|
||||
// assertIsolationWorks 内部完成:missing → insert → has 三段断言。
|
||||
$this->assertIsolationWorks();
|
||||
|
||||
// 显式成功标记(assertIsolationWorks 不带返回值,避免 risky test 告警)。
|
||||
$this->assertTrue(true, 'isolation probe inserted and is visible within the transaction');
|
||||
}
|
||||
|
||||
/**
|
||||
* 拒绝非测试库:临时把连接库名改为不含 "test" 的值,
|
||||
* 反射调用 protected assertTestDatabase 应触发 fail()。
|
||||
*
|
||||
* 使用 try/catch/finally 而非 expectException,目的是无论是否抛出
|
||||
* 都能在 finally 中恢复 config,避免污染后续测试。
|
||||
*/
|
||||
public function test_refuses_non_test_database(): void
|
||||
{
|
||||
// think 的 Config::set 不支持点号多级路径(见 bootstrap 注释),
|
||||
// 必须像 bootstrap 那样整段 pull 出来改了再 set 回去。
|
||||
$dbConfig = Config::get('database');
|
||||
$backup = is_array($dbConfig) ? $dbConfig : [];
|
||||
|
||||
$thrown = null;
|
||||
try {
|
||||
$dbConfig['connections']['main']['database'] = 'ulthon_admin_production_safe_marker';
|
||||
Config::set($dbConfig, 'database');
|
||||
|
||||
// 反射调用 protected assertTestDatabase(setUp 里已自动调过一次并通过,
|
||||
// 这里在事务内二次校验非测试库名,应当 fail)。
|
||||
$method = new ReflectionMethod(self::class, 'assertTestDatabase');
|
||||
$method->setAccessible(true);
|
||||
$method->invoke($this);
|
||||
} catch (AssertionFailedError $e) {
|
||||
$thrown = $e;
|
||||
} finally {
|
||||
// 无论是否抛出,恢复 config —— 不污染同一进程后续测试。
|
||||
Config::set($backup, 'database');
|
||||
}
|
||||
|
||||
$this->assertNotNull($thrown, 'assertTestDatabase should fail when database name lacks "test"');
|
||||
$this->assertStringContainsString('non-test database', $thrown->getMessage());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user