Login using System.Noticeably.Different.WebSite;
November 19, 2008 NoticeablyDifferent
Search for
 
Testing The Strategy Pattern 
Coming soon.
    #region Code
public abstract class Strategy {
    public abstract int AlgorithmInterface();
}
 
public class ConcreteStrategyA : Strategy {
    public override int AlgorithmInterface() {
        return 1;
    }
}
 
public class ConcreteStrategyB : Strategy {
    public override int AlgorithmInterface() {
        return 2;
    }
}
 
public class Context {
    private Strategy strategy;
 
    public Context(Strategy strategy) {
        this.strategy = strategy;
    }
 
    public int ContextInterface() {
        return strategy.AlgorithmInterface();
    }
}
    #endregion
 
    #region Unit Tests
public class MockStrategyA : Strategy {
    public const int ALGORITHM_RETURN_VALUE = 1;
 
    public override int AlgorithmInterface() {
        return ALGORITHM_RETURN_VALUE;
    }
}
 
public class MockStrategyB : Strategy {
    public const int ALGORITHM_RETURN_VALUE = 2;
 
    public override int AlgorithmInterface() {
        return ALGORITHM_RETURN_VALUE;
    }
}
 
[TestFixture]
public class ContextTests {
    private Context context;
    private Strategy strategy;
 
    public ContextTests() { }
 
    [Test]
    public void ContextInterfaceUsesSuppliedStrategyInContextInterface() {
        Assert.AreNotEqual(MockStrategyA.ALGORITHM_RETURN_VALUE, MockStrategyB.ALGORITHM_RETURN_VALUE,
            "Values for mocked strategies must differ for testing purposes");
        strategy = new MockStrategyA();
        context = new Context(strategy);
        Assert.AreEqual(MockStrategyA.ALGORITHM_RETURN_VALUE, context.ContextInterface(),
            "Context uses first strategy");
        strategy = new MockStrategyB();
        context = new Context(strategy);
        Assert.AreEqual(MockStrategyB.ALGORITHM_RETURN_VALUE, context.ContextInterface(),
            "Context uses second strategy");
    }
}
 
[TestFixture]
public class ConcreteStrategyATests {
    private Strategy strategy;
 
    public ConcreteStrategyATests() { }
 
    [SetUp]
    public void SetUp() {
        strategy = new ConcreteStrategyA();
    }
 
    [Test]
    public void AlgorithmInterfaceTest() {
        //TODO: Write unit tests for Concrete Strategies to ensure they return expected values.
    }
}
 
[TestFixture]
public class ConcreteStrategyBTests {
    private Strategy strategy;
 
    public ConcreteStrategyBTests() { }
 
    [SetUp]
    public void SetUp() {
        strategy = new ConcreteStrategyB();
    }
 
    [Test]
    public void AlgorithmInterfaceTest() {
        //TODO: Write unit tests for Concrete Strategies to ensure they return expected values.
    }
}
    #endregion
 
 
Passing a delegate to the context can provide similar behaviour and be equally testable.
 
In the sample below I pass delegates from the test fixture to the context to provide the desired change in the ContextInterface (strategy) of the Context.
 
    #region Code
public delegate int AlgorithmInterfaceHandler();
 
public class Context {
    private AlgorithmInterfaceHandler handler;
 
    public Context(AlgorithmInterfaceHandler handler) {
        this.handler = handler;
    }
 
    public int ContextInterface() {
        return handler();
    }
}
    #endregion
 
    #region Unit Tests
[TestFixture]
public class ContextTests {
    private Context context;
 
    private const int FIRST_HANDLER_RETURN_VALUE = 1;
    private AlgorithmInterfaceHandler firstHandler = delegate() {
        return FIRST_HANDLER_RETURN_VALUE;
    };
 
    private const int SECOND_HANDLER_RETURN_VALUE = 2;
    private AlgorithmInterfaceHandler secondHandler = delegate() {
        return SECOND_HANDLER_RETURN_VALUE;
    };
 
    public ContextTests() { }
 
    [Test]
    public void ContextInterfaceUsesSuppliedStrategyInContextInterface() {
        Assert.AreNotEqual(FIRST_HANDLER_RETURN_VALUE, SECOND_HANDLER_RETURN_VALUE,
            "Values for mocked strategies must differ for testing purposes");
        context = new Context(firstHandler);
        Assert.AreEqual(FIRST_HANDLER_RETURN_VALUE, context.ContextInterface(),
            "Context uses first strategy");
        context = new Context(secondHandler);
        Assert.AreEqual(SECOND_HANDLER_RETURN_VALUE, context.ContextInterface(),
            "Context uses second strategy");
    }
}
    #endregion