From 58f7a1184a9d3f1587ede3833df8429624562d3f Mon Sep 17 00:00:00 2001 From: Willem van den Ende Date: Mon, 14 Sep 2026 20:53:04 +0100 Subject: [PATCH] Add tests for ActiveRecord functionality (DbBase.Find, Client.FindByName, DbBase.Context singleton) --- tests/BeforeAfter.Tests/BeforeTests.cs | 134 +++++++++++++++++++++++++ 1 file changed, 134 insertions(+) diff --git a/tests/BeforeAfter.Tests/BeforeTests.cs b/tests/BeforeAfter.Tests/BeforeTests.cs index d9d94dc..24b23c2 100644 --- a/tests/BeforeAfter.Tests/BeforeTests.cs +++ b/tests/BeforeAfter.Tests/BeforeTests.cs @@ -159,4 +159,138 @@ public class BeforeTests DbBase.Context = null; // cleanup } + + // --------------------------------------------------------------------- + // (9) ActiveRecord finder: DbBase.Find walks the context's tracked + // entities, looks for the first whose runtime type matches T, + // and returns it when matches. + // --------------------------------------------------------------------- + [Fact] + public void DbBase_Find_finds_matching_entity() + { + var db = new DbContext(); + var acme = new Client { Name = "Acme" }; + var globex = new Client { Name = "Globex" }; + db.Attach(acme); + db.Attach(globex); + + var result = DbBase.Find(c => c.Name == "Globex", db); + + Assert.NotNull(result); + Assert.Same(globex, result); + } + + // --------------------------------------------------------------------- + // (10) DbBase.Find returns null when no entity of type T satisfies + // the predicate. + // --------------------------------------------------------------------- + [Fact] + public void DbBase_Find_returns_null_when_no_match() + { + var db = new DbContext(); + db.Attach(new Client { Name = "Acme" }); + + var result = DbBase.Find(c => c.Name == "Nobody", db); + + Assert.Null(result); + } + + // --------------------------------------------------------------------- + // (11) DbBase.Find filters by runtime type — an Order attached to the + // context does NOT match a Client predicate. + // --------------------------------------------------------------------- + [Fact] + public void DbBase_Find_ignores_non_matching_types() + { + var db = new DbContext(); + db.Attach(new Order { Description = "test" }); + + var result = DbBase.Find(_ => true, db); + + Assert.Null(result); + } + + // --------------------------------------------------------------------- + // (12) DbBase.Find returns the FIRST matching entity only. + // --------------------------------------------------------------------- + [Fact] + public void DbBase_Find_returns_first_match() + { + var db = new DbContext(); + var first = new Client { Name = "SameName" }; + var second = new Client { Name = "SameName" }; + db.Attach(first); + db.Attach(second); + + var result = DbBase.Find(c => c.Name == "SameName", db); + + Assert.Same(first, result); // first one inserted wins + Assert.NotSame(second, result); + } + + // --------------------------------------------------------------------- + // (13) DbBase.Find handles a null context gracefully. + // --------------------------------------------------------------------- + [Fact] + public void DbBase_Find_with_null_context_returns_default() + { + var result = DbBase.Find(_ => true, null); + Assert.Null(result); + } + + // --------------------------------------------------------------------- + // (14) Client.FindByName delegates to DbBase.Find and works correctly. + // --------------------------------------------------------------------- + [Fact] + public void Client_FindByName_finds_by_name() + { + var db = new DbContext(); + var acme = new Client { Name = "Acme Corp" }; + db.Attach(acme); + + var result = Client.FindByName("Acme Corp", db); + + Assert.NotNull(result); + Assert.Same(acme, result); + } + + // --------------------------------------------------------------------- + // (15) Client.FindByName returns null when the name does not match. + // --------------------------------------------------------------------- + [Fact] + public void Client_FindByName_returns_null_when_not_found() + { + var db = new DbContext(); + db.Attach(new Client { Name = "Acme Corp" }); + + var result = Client.FindByName("Nobody", db); + + Assert.Null(result); + } + + // --------------------------------------------------------------------- + // (16) The class-level DbBase.Context singleton can be used as the + // implicit context source for Find operations — the classic + // ActiveRecord pattern where any entity method reaches the shared + // context without parameter passing. + // --------------------------------------------------------------------- + [Fact] + public void DbBase_Context_singleton_is_used_in_Find() + { + var db = new DbContext(); + var targeted = new Client { Name = "TargetCo" }; + db.Attach(targeted); + + DbBase.Context = db; + + // Query using the singleton instead of passing the context: + // (In practice, callers often do this to avoid threading db through + // every call — the whole point of the ActiveRecord leak.) + var queryResult = DbBase.Find(c => c.Name == "TargetCo", DbBase.Context); + + Assert.NotNull(queryResult); + Assert.Same(targeted, queryResult); + + DbBase.Context = null; // cleanup + } } \ No newline at end of file