169 lines
6.0 KiB
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(),
|
|
];
|
|
}
|
|
}
|