diff --git a/src/DotJEM.NUnit3.Tests/Class1.cs b/src/DotJEM.NUnit3.Tests/Class1.cs
index 7b205fe..5195337 100644
--- a/src/DotJEM.NUnit3.Tests/Class1.cs
+++ b/src/DotJEM.NUnit3.Tests/Class1.cs
@@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
-using System.Runtime.Remoting.Messaging;
using System.Text;
using System.Threading.Tasks;
using NUnit.Framework;
diff --git a/src/DotJEM.NUnit3.Tests/Constraints/Objects/ObjectPropertiesEqualsConstraintTest.cs b/src/DotJEM.NUnit3.Tests/Constraints/Objects/ObjectPropertiesEqualsConstraintTest.cs
index d8f82df..8bf3b62 100644
--- a/src/DotJEM.NUnit3.Tests/Constraints/Objects/ObjectPropertiesEqualsConstraintTest.cs
+++ b/src/DotJEM.NUnit3.Tests/Constraints/Objects/ObjectPropertiesEqualsConstraintTest.cs
@@ -83,4 +83,79 @@ public void Test_InRunnerDisplay2()
Assert.That(new { Test = "243", Age = 42 }, Has.Properties.NotEqualTo(new { Test = "243", Age = 43 }).Strict());
}
}
+
+ ///
+ /// Tests for stack overflow regression introduced under .NET 9.0 where
+ /// InitializeProperties was recursing into static properties (e.g. DateTime.Now, DateTime.Today)
+ /// that return new values on each access, defeating the cycle-detection in the references set.
+ ///
+ public class ObjectPropertiesEqualsConstraintStackOverflowRegressionTest
+ {
+ private class WithDateTime
+ {
+ public DateTime CreatedAt { get; set; }
+ public string Name { get; set; }
+ }
+
+ private class Parent
+ {
+ public Child Child { get; set; }
+ }
+
+ private class Child
+ {
+ public Parent Parent { get; set; }
+ }
+
+ private class WithTypeProperty
+ {
+ public Type ObjectType { get; set; }
+ public string Name { get; set; }
+ }
+
+ [Test]
+ public void InitializeProperties_ObjectWithDateTimeProperty_DoesNotStackOverflow()
+ {
+ var expected = new WithDateTime { CreatedAt = new DateTime(2024, 1, 15, 10, 30, 0), Name = "test" };
+ Assert.DoesNotThrow(() =>
+ {
+ var constraint = new ObjectPropertiesEqualsConstraint(expected);
+ });
+ }
+
+ [Test]
+ public void ApplyTo_ObjectWithDateTimeProperty_Passes()
+ {
+ var expected = new WithDateTime { CreatedAt = new DateTime(2024, 1, 15, 10, 30, 0), Name = "test" };
+ var actual = new WithDateTime { CreatedAt = new DateTime(2024, 1, 15, 10, 30, 0), Name = "test" };
+
+ var constraint = new ObjectPropertiesEqualsConstraint(expected);
+ ConstraintResult result = constraint.ApplyTo(actual);
+
+ Assert.That(result.IsSuccess, Is.True, result.ToString());
+ }
+
+ [Test]
+ public void InitializeProperties_ObjectWithCircularReference_DoesNotStackOverflow()
+ {
+ var parent = new Parent();
+ var child = new Child { Parent = parent };
+ parent.Child = child;
+
+ Assert.DoesNotThrow(() =>
+ {
+ var constraint = new ObjectPropertiesEqualsConstraint(parent);
+ });
+ }
+
+ [Test]
+ public void InitializeProperties_ObjectWithTypeProperty_DoesNotStackOverflow()
+ {
+ var expected = new WithTypeProperty { ObjectType = typeof(string), Name = "test" };
+ Assert.DoesNotThrow(() =>
+ {
+ var constraint = new ObjectPropertiesEqualsConstraint(expected);
+ });
+ }
+ }
}
diff --git a/src/DotJEM.NUnit3.Tests/DotJEM.NUnit3.Tests.csproj b/src/DotJEM.NUnit3.Tests/DotJEM.NUnit3.Tests.csproj
index f00ffb8..c7eef21 100644
--- a/src/DotJEM.NUnit3.Tests/DotJEM.NUnit3.Tests.csproj
+++ b/src/DotJEM.NUnit3.Tests/DotJEM.NUnit3.Tests.csproj
@@ -1,6 +1,6 @@
- net48
+ net48;net9.0
DotJEM.NUnit3.Tests
DotJEM.NUnit3.Tests
Copyright © 2019
@@ -15,10 +15,11 @@
-
+
+
-
+
diff --git a/src/DotJEM.NUnit3/Constraints/Objects/ObjectPropertiesEqualsConstraint.cs b/src/DotJEM.NUnit3/Constraints/Objects/ObjectPropertiesEqualsConstraint.cs
index 5cc609f..ad63cbb 100644
--- a/src/DotJEM.NUnit3/Constraints/Objects/ObjectPropertiesEqualsConstraint.cs
+++ b/src/DotJEM.NUnit3/Constraints/Objects/ObjectPropertiesEqualsConstraint.cs
@@ -24,7 +24,7 @@ public class ObjectPropertiesEqualsConstraint : BaseConstraint, IObjectProper
protected T Expected { get; }
public bool ExplicitTypesFlag { get; set; }
- private readonly HashSet