diff UnitTests/CS/Patterns/DuckTypingTest.cs @ 0:f990fcb411a9

Копия текущей версии из github
author cin
date Thu, 27 Mar 2014 21:46:09 +0400
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/UnitTests/CS/Patterns/DuckTypingTest.cs	Thu Mar 27 21:46:09 2014 +0400
@@ -0,0 +1,327 @@
+using System;
+
+using NUnit.Framework;
+
+using BLToolkit.Patterns;
+
+namespace Patterns
+{
+	[TestFixture]
+	public class DuckTypingTest
+	{
+		public interface TestInterface
+		{
+			int  Method(int value);
+			void Method(int v1, out int v2);
+
+			int Prop { get; }
+
+			event EventHandler Event;
+
+			void CallEvent();
+		}
+
+		public interface TestInterface2
+		{
+			int  Method(int value);
+			void I2Method(int v1, out int v2);
+		}
+
+		public class TestClass
+		{
+			public static int Field;
+
+			public int Method(int value)
+			{
+				return value + 2;
+			}
+
+			public void Method(int v1, out int v2)
+			{
+				v2 = v1;
+			}
+
+			public void I2Method(int v1, out int v2)
+			{
+				v2 = v1;
+			}
+
+			public int Prop
+			{
+				get { return 22; }
+			}
+
+			public event EventHandler Event;
+
+			public void CallEvent()
+			{
+				Event(this, EventArgs.Empty);
+			}
+		}
+
+		[Test]
+		public void Test()
+		{
+			var duck  = DuckTyping.Implement<TestInterface> (new TestClass());
+			var same  = DuckTyping.Implement<TestInterface> (duck);
+			var duck2 = DuckTyping.Implement<TestInterface2>(same);
+
+			Assert.AreSame(duck, same);
+
+			int value;
+			duck.Method(33, out value);
+
+			Assert.AreEqual(33, value);
+			Assert.AreEqual(42, duck.Method(40));
+			Assert.AreEqual(22, duck.Prop);
+
+			duck.Event += duck_Event;
+
+			duck.CallEvent();
+
+			Assert.AreEqual(55, eventValue);
+
+			duck2.I2Method(33, out value);
+
+			Assert.AreEqual(33, value);
+			Assert.AreEqual(42, duck2.Method(40));
+		}
+
+		int eventValue;
+
+		void duck_Event(object sender, EventArgs e)
+		{
+			eventValue = 55;
+		}
+
+		public class Child1 : TestClass
+		{
+			public new int Method(int value)
+			{
+				return value + 5;
+			}
+		}
+
+		public class Child2 : TestClass
+		{
+			public new int Method(int value)
+			{
+				return value + 10;
+			}
+		}
+
+		[Test]
+		public void BulkTest()
+		{
+			var ducks  = DuckTyping.Implement<TestInterface,TestClass>(new Child1(), new Child2());
+
+			Assert.IsNotEmpty(ducks);
+			Assert.AreEqual(42, ducks[0].Method(40));
+			Assert.AreEqual(42, ducks[1].Method(40));
+		}
+
+		[Test]
+		public void BulkTest2()
+		{
+			var ducks = DuckTyping.Implement<TestInterface>(new Child1(), new Child2());
+
+			Assert.IsNotEmpty(ducks);
+			Assert.AreEqual(45, ducks[0].Method(40));
+			Assert.AreEqual(50, ducks[1].Method(40));
+		}
+		
+		[Test]
+		public void InheritanceTest()
+		{
+			var duck1 = DuckTyping.Implement<TestInterface>(new Child1());
+			var duck2 = DuckTyping.Implement<TestInterface>(new Child2());
+
+			Assert.AreNotSame(duck1, duck2);
+			Assert.AreEqual(45, duck1.Method(40));
+			Assert.AreEqual(50, duck2.Method(40));
+		}
+
+		[Test]
+		public void InheritanceTest2()
+		{
+			var duck1 = DuckTyping.Implement<TestInterface,TestClass>(new Child1());
+			var duck2 = DuckTyping.Implement<TestInterface,TestClass>(new Child2());
+
+			Assert.AreNotSame(duck1, duck2);
+			Assert.AreEqual(42, duck1.Method(40));
+			Assert.AreEqual(42, duck2.Method(40));
+		}
+
+		public class StaticClass
+		{
+			public static int Method(int value)
+			{
+				return value + 3;
+			}
+		}
+
+		[Test]
+		public void StaticTest()
+		{
+			DuckTyping.AllowStaticMembers = true;
+
+			var duck = DuckTyping.Implement<TestInterface,StaticClass>(new StaticClass());
+
+			Assert.AreEqual(43, duck.Method(40));
+		}
+
+		public struct TestStruct
+		{
+			public int Method(int value)
+			{
+				return value + 3;
+			}
+		}
+
+		[Test]
+		public void StructTest()
+		{
+			DuckTyping.AllowStaticMembers = true;
+
+			var duck = DuckTyping.Implement<TestInterface>(new TestStruct());
+
+			Assert.AreEqual(43, duck.Method(40));
+		}
+
+
+		public interface GenericInterface<T>
+		{
+			T Method(T value);
+		}
+
+		public class GenericClass<T>
+		{
+			public T Method(T value)
+			{
+				return value;
+			}
+
+			public void I2Method(int v1, out int v2)
+			{
+				v2 = v1 + 2;
+			}
+		}
+
+		[Test]
+		public void GenericInterfaceTest()
+		{
+			var o     = new GenericClass<int>();
+			var duck  = DuckTyping.Implement<GenericInterface<int>>(o);
+			var duck2 = DuckTyping.Implement<TestInterface2> (o);
+
+			Assert.AreEqual(40, duck .Method(40));
+			Assert.AreEqual(40, duck2.Method(40));
+
+			int value;
+			duck2.I2Method (33, out value);
+			Assert.AreEqual(35, value);
+		}
+
+		[Test, ExpectedException(typeof(ArgumentNullException))]
+		public void InvalidArgTest1()
+		{
+			TestInterface o = null;
+
+			var duck1 = DuckTyping.Implement<TestInterface>(o);
+			var duck2 = (TestInterface)DuckTyping.Implement(typeof(TestInterface), o);
+		}
+
+		interface NonPublicInterface
+		{
+		}
+
+		[Test, ExpectedException(typeof(ArgumentException))]
+		public void InvalidArgTest2()
+		{
+			var duck  = (NonPublicInterface)DuckTyping.Implement(typeof(NonPublicInterface), new TestClass());
+		}
+
+		[Test, ExpectedException(typeof(ArgumentException))]
+		public void InvalidArgTest3()
+		{
+			var duck  = (Child1)DuckTyping.Implement(typeof(Child1), new Child2());
+		}
+
+		[Test, ExpectedException(typeof(ArgumentException))]
+		public void InvalidArgTest4()
+		{
+			var duck  = (TestInterface)DuckTyping.Implement(typeof(TestInterface), typeof(TestInterface), new TestClass());
+		}
+
+		#region Aggregate
+
+		public interface IAggregatable
+		{
+			int Method1();
+			int Method2();
+		}
+
+		public interface IClass1
+		{
+			int Method1();
+			int Method3();
+		}
+
+		public interface IClass2
+		{
+			int Method2();
+		}
+
+		public class AggregateClass1: IClass1
+		{
+			public int Method1() { return 1; }
+			public int Method3() { return 3; }
+		}
+
+		public class AggregateClass2: IClass2
+		{
+			public int Method2() { return 2; }
+		}
+
+		[Test]
+		public void AggregateTest()
+		{
+			var duck  = DuckTyping.Aggregate<IAggregatable>(new AggregateClass1(), new AggregateClass2());
+
+			Assert.IsNotNull(duck);
+
+			Assert.AreEqual(1, duck.Method1());
+			Assert.AreEqual(2, duck.Method2());
+
+			// It is still possible to get access
+			// to an interface of an underlying object.
+			//
+			var cls2 = DuckTyping.Implement<IClass2>(duck);
+
+			Assert.IsNotNull(cls2);
+			Assert.AreEqual(2, cls2.Method2());
+
+			// Even to switch from one aggregated object to another
+			//
+			var cls1 = DuckTyping.Implement<IClass1>(cls2);
+
+			Assert.IsNotNull(cls1);
+			Assert.AreEqual(1, cls1.Method1());
+			Assert.AreEqual(3, cls1.Method3());
+		}
+
+		[Test]
+		public void MissedMethodsAggregateTest()
+		{
+			var duck = DuckTyping.Aggregate<IClass1>(new Version(1,0), Guid.NewGuid());
+
+			Assert.That(duck, Is.Not.Null);
+
+			// Neither System.Guid nor System.Version will ever have Method1.
+			//
+			Assert.That(duck.Method1(), Is.EqualTo(0));
+		}
+
+		#endregion
+	}
+}