CaiWuXiTong/tests/Unit/EcommerceFinance/UpstreamSchemaCatalogSynchronizerTest.php

169 lines
6.0 KiB
PHP

<?php
namespace Tests\Unit\EcommerceFinance;
use Illuminate\Support\Facades\DB;
use Mockery;
use Modules\EcommerceFinance\Services\UpstreamReadOnlyQuery;
use Modules\EcommerceFinance\Services\UpstreamReadOnlyQueryFactory;
use Modules\EcommerceFinance\Services\UpstreamSchemaCatalogSynchronizer;
use Modules\EcommerceFinance\Services\UpstreamSourceRegistry;
use Tests\TestCase;
class UpstreamSchemaCatalogSynchronizerTest extends TestCase
{
protected function setUp(): void
{
parent::setUp();
config([
'upstreams.local_configuration.enabled' => true,
'upstreams.sources.catalog_test' => [
'label' => '测试上游库',
'config' => 'catalog_test',
],
'catalog_test.enabled' => true,
]);
}
public function test_complete_metadata_result_replaces_one_source_catalog(): void
{
DB::table('upstream_schema_columns')->insert($this->existingRow());
$query = Mockery::mock(UpstreamReadOnlyQuery::class);
$query->shouldReceive('select')->once()->andReturn([
[
'schema_name' => 'rpt',
'object_name' => 'finance_summary',
'object_type' => 'view',
'column_name' => 'company_code',
'ordinal_position' => 1,
'data_type' => 'nvarchar',
'max_length' => 50,
'numeric_precision' => null,
'numeric_scale' => null,
'is_nullable' => 'NO',
],
[
'schema_name' => 'rpt',
'object_name' => 'finance_summary',
'object_type' => 'view',
'column_name' => 'amount',
'ordinal_position' => 2,
'data_type' => 'decimal',
'max_length' => null,
'numeric_precision' => 18,
'numeric_scale' => 2,
'is_nullable' => 'YES',
],
]);
$factory = Mockery::mock(UpstreamReadOnlyQueryFactory::class);
$factory->shouldReceive('forSource')->once()->with('catalog_test')->andReturn($query);
$result = (new UpstreamSchemaCatalogSynchronizer(
app(UpstreamSourceRegistry::class),
$factory
))->sync('catalog_test');
$this->assertSame(1, $result['objects']);
$this->assertSame(2, $result['columns']);
$this->assertDatabaseMissing('upstream_schema_columns', ['column_name' => 'old_column']);
$this->assertDatabaseHas('upstream_schema_columns', [
'source_key' => 'catalog_test',
'schema_name' => 'rpt',
'object_name' => 'finance_summary',
'column_name' => 'amount',
'data_type' => 'decimal',
'numeric_precision' => 18,
'numeric_scale' => 2,
'is_nullable' => true,
]);
}
public function test_empty_metadata_result_keeps_previous_catalog(): void
{
DB::table('upstream_schema_columns')->insert($this->existingRow());
$query = Mockery::mock(UpstreamReadOnlyQuery::class);
$query->shouldReceive('select')->once()->andReturn([]);
$factory = Mockery::mock(UpstreamReadOnlyQueryFactory::class);
$factory->shouldReceive('forSource')->once()->andReturn($query);
try {
(new UpstreamSchemaCatalogSynchronizer(
app(UpstreamSourceRegistry::class),
$factory
))->sync('catalog_test');
$this->fail('空目录不应覆盖原有数据字典。');
} catch (\RuntimeException) {
$this->assertDatabaseHas('upstream_schema_columns', [
'source_key' => 'catalog_test',
'column_name' => 'old_column',
]);
}
}
public function test_duplicate_metadata_rows_do_not_abort_catalog_sync(): void
{
$duplicate = [
'schema_name' => 'dbo',
'object_name' => 'tuihuo',
'object_type' => 'table',
'column_name' => '发货量',
'ordinal_position' => 3,
'data_type' => 'decimal',
'max_length' => null,
'numeric_precision' => 18,
'numeric_scale' => 2,
'is_nullable' => 'YES',
];
$query = Mockery::mock(UpstreamReadOnlyQuery::class);
$query->shouldReceive('select')->once()->andReturn([
$duplicate,
$duplicate,
[
...$duplicate,
'column_name' => '序号',
'ordinal_position' => 1,
'data_type' => 'int',
'numeric_precision' => 10,
'numeric_scale' => 0,
],
]);
$factory = Mockery::mock(UpstreamReadOnlyQueryFactory::class);
$factory->shouldReceive('forSource')->once()->with('catalog_test')->andReturn($query);
$result = (new UpstreamSchemaCatalogSynchronizer(
app(UpstreamSourceRegistry::class),
$factory
))->sync('catalog_test');
$this->assertSame(1, $result['objects']);
$this->assertSame(2, $result['columns']);
$this->assertSame(1, DB::table('upstream_schema_columns')
->where('source_key', 'catalog_test')
->where('schema_name', 'dbo')
->where('object_name', 'tuihuo')
->where('column_name', '发货量')
->count());
}
private function existingRow(): array
{
return [
'source_key' => 'catalog_test',
'schema_name' => 'dbo',
'object_name' => 'old_table',
'object_type' => 'table',
'column_name' => 'old_column',
'ordinal_position' => 1,
'data_type' => 'int',
'max_length' => null,
'numeric_precision' => 10,
'numeric_scale' => 0,
'is_nullable' => false,
'synchronized_at' => now()->subDay(),
'created_at' => now()->subDay(),
'updated_at' => now()->subDay(),
];
}
}