diff --git a/src/tests/Dragon-ISO.Engine.Tests/Fakes/FakeNdiInterop.cs b/src/tests/Dragon-ISO.Engine.Tests/Fakes/FakeNdiInterop.cs
index f5e35bb..e8cac1f 100644
--- a/src/tests/Dragon-ISO.Engine.Tests/Fakes/FakeNdiInterop.cs
+++ b/src/tests/Dragon-ISO.Engine.Tests/Fakes/FakeNdiInterop.cs
@@ -24,12 +24,35 @@ public sealed class FakeNdiInterop : INdiInterop
/// Per-output groups string seen by ; null = default Public.
public Dictionary SenderGroups { get; } = new();
+ ///
+ /// Number of finders created so far (initial construction + every rebuild).
+ /// Lets tests assert how many times the discovery service tried to rebuild.
+ ///
+ public int FinderCreatedCount { get; private set; }
+
+ ///
+ /// Optional hook invoked at the top of every call,
+ /// receiving the 1-based creation ordinal. Throw from here to simulate a runtime
+ /// that refuses to build a finder (e.g. the rebuild-failure path); return normally
+ /// to allow creation. Null (default) = always succeed.
+ ///
+ public Action? CreateFinderHook { get; set; }
+
public NdiFindHandle CreateFinder(string? groups = null)
{
+ FinderCreatedCount++;
+ CreateFinderHook?.Invoke(FinderCreatedCount);
LastFinderGroups = groups;
return new FakeFindHandle();
}
- public IReadOnlyList GetCurrentSources(NdiFindHandle finder) => Sources.ToArray();
+
+ public IReadOnlyList GetCurrentSources(NdiFindHandle finder)
+ {
+ if (finder is FakeFindHandle { Disposed: true })
+ throw new ObjectDisposedException(nameof(FakeFindHandle),
+ "GetCurrentSources called on a finder that was already disposed.");
+ return Sources.ToArray();
+ }
public NdiReceiverHandle CreateReceiver(string sourceFullName)
{
@@ -72,7 +95,8 @@ public sealed class FakeNdiInterop : INdiInterop
private sealed class FakeFindHandle : NdiFindHandle
{
- public override void Dispose() { }
+ public bool Disposed { get; private set; }
+ public override void Dispose() => Disposed = true;
}
private sealed class FakeReceiverHandle : NdiReceiverHandle