Files
MBN_STOCK_WEBVIEW/tests/MBN_STOCK_WEBVIEW.LegacyApplication.Tests/LegacyParityStockSearchServiceTests.cs

116 lines
4.4 KiB
C#

using System.Data;
using MBN_STOCK_WEBVIEW.LegacyApplication;
using MMoneyCoderSharp.Data;
namespace MBN_STOCK_WEBVIEW.LegacyApplication.Tests;
public sealed class LegacyParityStockSearchServiceTests
{
[Fact]
public async Task Search_PreservesProviderAndRowOrderWithoutLimitOrSort()
{
var executor = new RecordingExecutor(new Dictionary<string, DataTable>
{
["LEGACY_PARITY_KOSPI_MASTER"] = Table(("중복", "000001")),
["LEGACY_PARITY_KOSDAQ_MASTER"] = Table(("중복", "100001")),
["LEGACY_PARITY_NXT_KOSPI_MASTER"] = Table(("중복(NXT)", "200001")),
["LEGACY_PARITY_NXT_KOSDAQ_MASTER"] = Table(("중복", "300001")),
["LEGACY_PARITY_KOSPI"] = Table(("가-2", "000002"), ("가-1", "000001")),
["LEGACY_PARITY_KOSDAQ"] = Table(("나", "100001")),
["LEGACY_PARITY_NXT_KOSPI"] = Table(("다(NXT)", "200001")),
["LEGACY_PARITY_NXT_KOSDAQ"] = Table(("라(NXT)", "300001"))
});
var service = new LegacyParityStockSearchService(executor);
var result = await service.SearchAsync(" a%_ ");
Assert.Equal(["가-2", "가-1", "나", "다(NXT)", "라(NXT)"], result.DisplayNames);
Assert.Equal("300001", result.ResolveLastByDisplayName("중복")?.StockCode);
Assert.Equal(LegacyDomesticStockMarket.NxtKosdaq,
result.ResolveLastByDisplayName("중복")?.Market);
Assert.Equal(8, executor.Calls.Count);
foreach (var call in executor.Calls.Skip(4))
{
Assert.DoesNotContain("ORDER BY", call.Spec.Sql, StringComparison.OrdinalIgnoreCase);
Assert.DoesNotContain("LIMIT", call.Spec.Sql, StringComparison.OrdinalIgnoreCase);
Assert.DoesNotContain("ROWNUM", call.Spec.Sql, StringComparison.OrdinalIgnoreCase);
Assert.Single(call.Spec.Parameters);
Assert.Equal(" A%_ ", call.Spec.Parameters[0].Value);
}
}
[Fact]
public async Task EmptySearch_IsAllowedAndMasterSnapshotIsCached()
{
var tables = new Dictionary<string, DataTable>();
foreach (var name in new[]
{
"LEGACY_PARITY_KOSPI", "LEGACY_PARITY_KOSDAQ",
"LEGACY_PARITY_NXT_KOSPI", "LEGACY_PARITY_NXT_KOSDAQ"
})
{
tables[name] = Table();
tables[$"{name}_MASTER"] = Table();
}
var executor = new RecordingExecutor(tables);
var service = new LegacyParityStockSearchService(executor);
await service.SearchAsync(string.Empty);
await service.SearchAsync(string.Empty);
Assert.Equal(12, executor.Calls.Count);
Assert.Equal(4, executor.Calls.Count(call => call.TableName.EndsWith("_MASTER", StringComparison.Ordinal)));
Assert.All(executor.Calls.Where(call => !call.TableName.EndsWith("_MASTER", StringComparison.Ordinal)),
call => Assert.Equal(string.Empty, call.Spec.Parameters[0].Value));
}
private static DataTable Table(params (string Name, string Code)[] rows)
{
var table = new DataTable();
table.Columns.Add("STOCK_NAME", typeof(string));
table.Columns.Add("STOCK_CODE", typeof(string));
foreach (var row in rows)
{
table.Rows.Add(row.Name, row.Code);
}
return table;
}
private sealed class RecordingExecutor : IDataQueryExecutor
{
private readonly IReadOnlyDictionary<string, DataTable> _tables;
public RecordingExecutor(IReadOnlyDictionary<string, DataTable> tables)
{
_tables = tables;
}
public List<Call> Calls { get; } = [];
public DataTable Execute(DataSourceKind source, string tableName, string query) =>
throw new NotSupportedException();
public Task<DataTable> ExecuteAsync(
DataSourceKind source,
string tableName,
string query,
CancellationToken cancellationToken = default) =>
throw new NotSupportedException();
public Task<DataTable> ExecuteAsync(
DataSourceKind source,
string tableName,
DataQuerySpec query,
CancellationToken cancellationToken = default)
{
Calls.Add(new Call(source, tableName, query));
return Task.FromResult(_tables[tableName].Copy());
}
}
private sealed record Call(DataSourceKind Source, string TableName, DataQuerySpec Spec);
}