R3 Slice 3: CongressTrading-Modul + Worker-Log + core_settings auf EF Core - Modul: CongressTradingDbContext (ct_congressMember/ct_trade) + Design-Time-Factory; CongressRepository von Dapper auf EF; CongressTrade.DetailsFetched ergaenzt; Dapper entfernt - Core: CoreSettingsService (core_settings via EF); WorkerBase-Log auf EF (core_worker_log); 7 Worker-Ctors DatabaseService -> IDbContextFactory<CoreDbContext> - CoreMigrations + CongressMigrations (Dapper) entfernt; core_-Schema nun rein EF - EF-Migration InitialCongressTrading; AddCorePersistence-Fallback fuer leeren Connection-String (App startet ohne DB); Connection aus appsettings.Local.json (gitignored) - Tests: +4 CongressRepository (EF-InMemory) -> 39/39 gruen; Build + smoke-ui + App-Start ok Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> @
79 lines
2.7 KiB
C#
79 lines
2.7 KiB
C#
using FluentAssertions;
|
||
using IBKRTrader.Core.Modularity;
|
||
using IBKRTrader.Core.Workers;
|
||
using IBKRTrader.Modules.CongressTrading;
|
||
using IBKRTrader.Modules.CongressTrading.Database;
|
||
using IBKRTrader.Modules.CongressTrading.Scraper;
|
||
using IBKRTrader.Modules.CongressTrading.Workers;
|
||
using Microsoft.Extensions.Configuration;
|
||
using Microsoft.Extensions.DependencyInjection;
|
||
using NSubstitute;
|
||
|
||
namespace IBKRTrader.Tests.Modules;
|
||
|
||
[Trait("cat", "unit")]
|
||
public class CongressTradingModuleTests
|
||
{
|
||
private sealed class CapturingUiHost : IModuleUiHost
|
||
{
|
||
private readonly List<ModuleView> _views = new();
|
||
public IReadOnlyList<ModuleView> Views => _views;
|
||
public void RegisterView(ModuleView view) => _views.Add(view);
|
||
public bool IsOpen(string viewId) => false;
|
||
public void OpenView(string viewId) { }
|
||
public void ActivateMain() { }
|
||
public void RequestShutdown() { }
|
||
public event Action? OpenStateChanged { add { } remove { } }
|
||
}
|
||
|
||
[Fact]
|
||
public void Metadata_IsAsExpected()
|
||
{
|
||
var module = new CongressTradingModule();
|
||
|
||
module.Name.Should().Be("CongressTrading");
|
||
module.DbPrefix.Should().Be("ct_");
|
||
}
|
||
|
||
[Fact]
|
||
public void RegisterServices_RegistersServicesAndWorkers()
|
||
{
|
||
var services = new ServiceCollection();
|
||
|
||
new CongressTradingModule().RegisterServices(services, Substitute.For<IConfiguration>());
|
||
|
||
var types = services.Select(d => d.ServiceType).ToList();
|
||
types.Should().Contain(new[]
|
||
{
|
||
typeof(CongressRepository),
|
||
typeof(CapitolTradesScraper),
|
||
typeof(CongressHistoryImportWorker),
|
||
typeof(CongressScrapeWorker),
|
||
});
|
||
// Worker werden zusätzlich als IWorker registriert (für die WorkerEngine).
|
||
services.Count(d => d.ServiceType == typeof(IWorker)).Should().Be(2);
|
||
}
|
||
|
||
[Fact]
|
||
public void RegisterUi_RegistersMainView()
|
||
{
|
||
var host = new CapturingUiHost();
|
||
// CreateForm wird hier NICHT aufgerufen – daher genügt ein leerer Provider.
|
||
var provider = new ServiceCollection().BuildServiceProvider();
|
||
|
||
new CongressTradingModule().RegisterUi(host, provider);
|
||
|
||
host.Views.Should().ContainSingle();
|
||
host.Views[0].Id.Should().Be("congresstrading.main");
|
||
host.Views[0].Title.Should().Be("Congress Trading");
|
||
}
|
||
|
||
[Fact]
|
||
public void GetActivationBlocker_DefaultsToNull()
|
||
{
|
||
// Default-Interface-Methode → über die Interface-Referenz aufrufen.
|
||
IModule module = new CongressTradingModule();
|
||
module.GetActivationBlocker(Substitute.For<IConfiguration>()).Should().BeNull();
|
||
}
|
||
}
|