using System; using NUnit.Framework; namespace FluentSample { public interface IFluentCounter { IFluentCounter Increase(); IFluentCounter Decrease(); int Value { get; } } public interface IFluentCounter : IFluentCounter where T : IFluentCounter { new T Increase(); new T Decrease(); } public class NaturalCounter : IFluentCounter { private readonly Int32 _value; public NaturalCounter(Int32 value) { _value = value; } #region IFluentCounter Members public NaturalCounter Increase() { return new NaturalCounter(_value + 1); } public NaturalCounter Decrease() { if (_value > 0) return new NaturalCounter(_value - 1); return new NaturalCounter(0); } #endregion #region IFluentCounter Members public int Value { get { return _value; } } IFluentCounter IFluentCounter.Increase() { return Increase(); } IFluentCounter IFluentCounter.Decrease() { return Decrease(); } #endregion } public class EchoingCounter : IFluentCounter> where T : IFluentCounter { private readonly T _inner; public EchoingCounter(T inner) { _inner = inner; } #region IFluentCounter> Members public EchoingCounter Increase() { Console.WriteLine(System.Reflection.MethodBase.GetCurrentMethod().Name); return new EchoingCounter(_inner.Increase()); } public EchoingCounter Decrease() { Console.WriteLine(System.Reflection.MethodBase.GetCurrentMethod().Name); return new EchoingCounter(_inner.Decrease()); } #endregion #region IFluentCounter Members public int Value { get { return _inner.Value; } } IFluentCounter IFluentCounter.Increase() { return Increase(); } IFluentCounter IFluentCounter.Decrease() { return Decrease(); } #endregion } public abstract class FluentCounterImplementationsTesterBase where T : IFluentCounter { protected abstract T StartWith(Int32 value); [Test] public void Increase_twiceFromZero_produceANewInstanceWithValue2() { // arrange: T toTest = StartWith(0); // act: T result = toTest.Increase().Increase(); // assert: Assert.AreNotSame(toTest, result); Assert.AreEqual(2, result.Value); } [Test] public void Decrease_twiceFromFour_produceANewInstanceWithValue2() { // arrange: T toTest = StartWith(4); // act: T result = toTest.Decrease().Decrease(); // assert: Assert.AreNotSame(toTest, result); Assert.AreEqual(2, result.Value); } } [TestFixture] public class NaturalCounterTester : FluentCounterImplementationsTesterBase { protected override NaturalCounter StartWith(Int32 value) { return new NaturalCounter(value); } } [TestFixture] public class EchoingCounterTester : FluentCounterImplementationsTesterBase> { protected override EchoingCounter StartWith(Int32 value) { return new EchoingCounter(new NaturalCounter(value)); } } }