169 lines
5.4 KiB
PHP
169 lines
5.4 KiB
PHP
|
|
<?php
|
||
|
|
|
||
|
|
declare(strict_types=1);
|
||
|
|
|
||
|
|
namespace HyperfTest\Cases\Unit\Service;
|
||
|
|
|
||
|
|
use App\Service\DashboardStatsService;
|
||
|
|
use PHPUnit\Framework\TestCase;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* DashboardStatsService 单元测试
|
||
|
|
*
|
||
|
|
* 覆盖常量定义、枚举校验等纯逻辑(聚合查询由集成测试覆盖)
|
||
|
|
*
|
||
|
|
* @internal
|
||
|
|
* @coversNothing
|
||
|
|
*/
|
||
|
|
class DashboardStatsServiceTest extends TestCase
|
||
|
|
{
|
||
|
|
private DashboardStatsService $service;
|
||
|
|
|
||
|
|
protected function setUp(): void
|
||
|
|
{
|
||
|
|
parent::setUp();
|
||
|
|
$this->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);
|
||
|
|
}
|
||
|
|
}
|