service = new DashboardStatsService(); } // ========== 常量校验 ========== public function test_valid_data_types_contains_all_expected_types(): void { $types = DashboardStatsService::VALID_DATA_TYPES; $this->assertContains('order', $types); $this->assertContains('product', $types); $this->assertContains('refund', $types); $this->assertContains('inventory', $types); $this->assertCount(4, $types); } public function test_valid_group_by_contains_all_expected_values(): void { $values = DashboardStatsService::VALID_GROUP_BY; $this->assertContains('day', $values); $this->assertContains('week', $values); $this->assertContains('month', $values); $this->assertCount(3, $values); } public function test_valid_dimensions_contains_all_expected_values(): void { $values = DashboardStatsService::VALID_DIMENSIONS; $this->assertContains('company', $values); $this->assertContains('platform', $values); $this->assertContains('store', $values); $this->assertCount(3, $values); } // ========== buildScopeCondition(通过反射测试私有方法) ========== public function test_build_scope_condition_all_returns_empty(): void { $bindings = ['2026-01-01', '2026-01-31']; $result = $this->invokeBuildScope('all', [], $bindings); $this->assertSame('', $result); $this->assertCount(2, $bindings); } public function test_build_scope_condition_store_returns_in_clause(): void { $bindings = ['2026-01-01', '2026-01-31']; $result = $this->invokeBuildScope('store', [1, 2, 3], $bindings); $this->assertStringContainsString('store_id IN', $result); $this->assertCount(5, $bindings); // 2 原始 + 3 scope_ids $this->assertSame(1, $bindings[2]); $this->assertSame(2, $bindings[3]); $this->assertSame(3, $bindings[4]); } public function test_build_scope_condition_platform_returns_in_clause(): void { $bindings = ['2026-01-01', '2026-01-31']; $result = $this->invokeBuildScope('platform', [10, 20], $bindings); $this->assertStringContainsString('platform_id IN', $result); $this->assertCount(4, $bindings); } public function test_build_scope_condition_empty_ids_returns_empty(): void { $bindings = ['2026-01-01', '2026-01-31']; $result = $this->invokeBuildScope('store', [], $bindings); $this->assertSame('', $result); $this->assertCount(2, $bindings); } // ========== getDateTrunc(通过反射测试私有方法) ========== public function test_date_trunc_day(): void { $result = $this->invokeGetDateTrunc('day'); $this->assertStringContainsString("'day'", $result); $this->assertStringContainsString('DATE_TRUNC', $result); } public function test_date_trunc_week(): void { $result = $this->invokeGetDateTrunc('week'); $this->assertStringContainsString("'week'", $result); } public function test_date_trunc_month(): void { $result = $this->invokeGetDateTrunc('month'); $this->assertStringContainsString("'month'", $result); } // ========== TYPE_TABLE_MAP 映射 ========== public function test_type_table_map_covers_order_product_refund(): void { $reflection = new \ReflectionClass(DashboardStatsService::class); $constant = $reflection->getReflectionConstant('TYPE_TABLE_MAP'); $map = $constant->getValue(); $this->assertSame('orders', $map['order']); $this->assertSame('products', $map['product']); $this->assertSame('refunds', $map['refund']); $this->assertArrayNotHasKey('inventory', $map); } public function test_dimension_table_map_covers_all_dimensions(): void { $reflection = new \ReflectionClass(DashboardStatsService::class); $constant = $reflection->getReflectionConstant('DIMENSION_TABLE_MAP'); $map = $constant->getValue(); $this->assertArrayHasKey('company', $map); $this->assertArrayHasKey('platform', $map); $this->assertArrayHasKey('store', $map); foreach ($map as $config) { $this->assertArrayHasKey('table', $config); $this->assertArrayHasKey('name_field', $config); } } // ========== Helper ========== private function invokeBuildScope(string $scope_type, array $scope_ids, array &$bindings): string { $method = new \ReflectionMethod(DashboardStatsService::class, 'buildScopeCondition'); $args = [$scope_type, $scope_ids, &$bindings]; return $method->invokeArgs($this->service, $args); } private function invokeGetDateTrunc(string $group_by): string { $method = new \ReflectionMethod(DashboardStatsService::class, 'getDateTrunc'); $method->setAccessible(true); return $method->invoke($this->service, $group_by); } }