CaiWuXiTong/tests/Feature/Console/SupplierManagementMirrorSyncCommandTest.php

98 lines
4.7 KiB
PHP

<?php
namespace Tests\Feature\Console;
use Illuminate\Contracts\Console\Kernel;
use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Support\Carbon;
use Mockery;
use Modules\EcommerceFinance\Services\BusinessMirrorDatasetRegistry;
use Modules\EcommerceFinance\Services\BusinessMirrorSynchronizer;
use RuntimeException;
use Tests\TestCase;
class SupplierManagementMirrorSyncCommandTest extends TestCase
{
private const DATASETS = [
'jiansun.dbo.js_supplier_View',
'jiansun.dbo.js_supplier_contract_View',
'jiansun.dbo.js_supplier_linkers',
'jiansun.dbo.js_supplier_payinfo',
];
public function test_daily_sync_finishes_all_four_datasets_in_order(): void
{
config(['upstream_mirrors.refresh_enabled' => true]);
$registry = Mockery::mock(BusinessMirrorDatasetRegistry::class);
$sync = Mockery::mock(BusinessMirrorSynchronizer::class);
foreach (self::DATASETS as $key) {
$registry->shouldReceive('scheduled')->once()->with($key)->andReturn(true);
$sync->shouldReceive('sync')->once()->with($key, true, null, 0)->ordered()
->andReturn(['status' => 'succeeded', 'batches' => 3, 'rows' => 1200]);
}
$this->app->instance(BusinessMirrorDatasetRegistry::class, $registry);
$this->app->instance(BusinessMirrorSynchronizer::class, $sync);
$this->artisan('business-mirror:sync-supplier-management')->assertSuccessful();
}
public function test_one_failure_does_not_prevent_other_supplier_data_from_refreshing(): void
{
config(['upstream_mirrors.refresh_enabled' => true]);
$registry = Mockery::mock(BusinessMirrorDatasetRegistry::class);
$sync = Mockery::mock(BusinessMirrorSynchronizer::class);
foreach (self::DATASETS as $index => $key) {
$registry->shouldReceive('scheduled')->once()->with($key)->andReturn(true);
$expectation = $sync->shouldReceive('sync')->once()->with($key, true, null, 0)->ordered();
if ($index === 0) $expectation->andThrow(new RuntimeException('upstream unavailable'));
else $expectation->andReturn(['status' => 'succeeded', 'batches' => 1, 'rows' => 5]);
}
$this->app->instance(BusinessMirrorDatasetRegistry::class, $registry);
$this->app->instance(BusinessMirrorSynchronizer::class, $sync);
$this->artisan('business-mirror:sync-supplier-management')
->expectsOutputToContain('同步失败')->assertExitCode(1);
}
public function test_local_refresh_disabled_never_reads_upstream(): void
{
config(['upstream_mirrors.refresh_enabled' => false]);
$registry = Mockery::mock(BusinessMirrorDatasetRegistry::class);
$registry->shouldNotReceive('scheduled');
$sync = Mockery::mock(BusinessMirrorSynchronizer::class);
$sync->shouldNotReceive('sync');
$this->app->instance(BusinessMirrorDatasetRegistry::class, $registry);
$this->app->instance(BusinessMirrorSynchronizer::class, $sync);
$this->artisan('business-mirror:sync-supplier-management')->assertSuccessful();
}
public function test_disabled_supplier_datasets_are_not_synced(): void
{
config(['upstream_mirrors.refresh_enabled' => true]);
$registry = Mockery::mock(BusinessMirrorDatasetRegistry::class);
$registry->shouldReceive('scheduled')->times(4)->andReturn(false);
$sync = Mockery::mock(BusinessMirrorSynchronizer::class);
$sync->shouldNotReceive('sync');
$this->app->instance(BusinessMirrorDatasetRegistry::class, $registry);
$this->app->instance(BusinessMirrorSynchronizer::class, $sync);
$this->artisan('business-mirror:sync-supplier-management')->assertSuccessful();
}
public function test_schedule_runs_at_0815_shanghai_even_when_app_timezone_is_utc(): void
{
config(['app.installed' => true, 'app.schedule_time' => '09:00', 'app.timezone' => 'UTC']);
$schedule = new Schedule('UTC');
(new \ReflectionMethod(\App\Console\Kernel::class, 'schedule'))->invoke($this->app->make(Kernel::class), $schedule);
$events = collect($schedule->events())
->filter(fn ($event) => str_contains($event->command ?? '', 'business-mirror:sync-supplier-management'));
$this->assertCount(1, $events);
$event = $events->first();
try {
foreach (['00:14' => false, '00:15' => true, '00:16' => false] as $time => $due) {
Carbon::setTestNow(Carbon::parse('2026-10-12 ' . $time . ':00', 'UTC'));
$this->assertSame($due, $event->isDue($this->app), $time);
}
} finally {
Carbon::setTestNow();
}
}
}