using Moq; using NUnit.Framework; using StructureHelperCommon.Infrastructures.Exceptions; using StructureHelperCommon.Infrastructures.Interfaces; namespace StructureHelperTests.UnitTests.UpdateStrategiesTests { [TestFixture] public class DeepCloningStrategyTests { private DeepCloningStrategy _strategy; [SetUp] public void SetUp() { _strategy = new DeepCloningStrategy(); } [Test] public void Clone_WithNullOriginal_ReturnsNull() { // Act var result = _strategy.Clone(null); // Assert Assert.IsNull(result); } [Test] public void Clone_WhenObjectAlreadyCloned_ReturnsExistingClone() { // Arrange var original = new Mock().Object; var expectedClone = new Mock().Object; // Use reflection to populate the internal dictionary (_clonedObjects) var clonedObjects = new Dictionary { { original, expectedClone } }; var internalField = typeof(DeepCloningStrategy).GetField("_clonedObjects", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); internalField.SetValue(_strategy, clonedObjects); // Act var result = _strategy.Clone(original); // Assert Assert.AreSame(expectedClone, result); } [Test] public void Clone_WithCustomCloneStrategy_UsesCloneStrategyToCloneObject() { // Arrange var original = new Mock().Object; var expectedClone = new Mock().Object; var cloneStrategyMock = new Mock>(); cloneStrategyMock.Setup(cs => cs.GetClone(original)).Returns(expectedClone); // Act var result = _strategy.Clone(original, cloneStrategyMock.Object); // Assert Assert.AreSame(expectedClone, result); cloneStrategyMock.Verify(cs => cs.GetClone(original), Times.Once); } [Test] public void Clone_WhenObjectImplementsICloneable_UsesCloneMethod() { // Arrange var originalMock = new Mock(); var expectedClone = new Mock().Object; originalMock.Setup(o => o.Clone()).Returns(expectedClone); // Act var result = _strategy.Clone(originalMock.Object); // Assert Assert.AreSame(expectedClone, result); originalMock.Verify(o => o.Clone(), Times.Once); } [Test] public void Clone_WhenObjectNotCloneableAndNoCloneStrategy_ThrowsStructureHelperException() { // Arrange var original = new object(); // Not ICloneable // Act & Assert var exception = Assert.Throws(() => _strategy.Clone(original)); Assert.That(exception.Message, Does.Contain("object is not IClonable and cloning strategy is null")); } [Test] public void Clone_AddsClonedObjectToDictionary() { // Arrange var originalMock = new Mock(); var expectedClone = new Mock().Object; originalMock.Setup(o => o.Clone()).Returns(expectedClone); // Act var result = _strategy.Clone(originalMock.Object); // Use reflection to check the private dictionary (_clonedObjects) var internalField = typeof(DeepCloningStrategy).GetField("_clonedObjects", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); var clonedObjects = (Dictionary)internalField.GetValue(_strategy); // Assert Assert.AreSame(expectedClone, clonedObjects[originalMock.Object]); } } }