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()); } }