Click here to Skip to main content
15,895,833 members
Articles / Desktop Programming / Win32

Evolving Responsible, Self-Describing Components

Rate me:
Please Sign up or sign in to vote.
4.81/5 (9 votes)
25 Apr 2008CPOL21 min read 23.1K   64   29  
How self-describing components can emerge from responsibility-driven development practices, and how use of the Visual Studio 'code regions' tool can add value to this process.
/*
 * Copyright 2008 Oculo Consulting Limited
 * 
*/
using System;
using MbUnit.Framework;
using Rhino.Mocks;
using ResponsibilitiesExample;

namespace ResponsibleRegionsExample.Tests
{
    [TestFixture]
    public class BufferedChannelQueueTests
    {
        private MockRepository _mocks;
        private const int _QUEUE_CAPACITY = 3;

        #region SetUp & TearDown

        [SetUp]
        public void SetUp()
        {
            _mocks = new MockRepository();
        }

        [TearDown]
        public void TearDown()
        {
            _mocks.VerifyAll();
        }

        #endregion

        #region Responsibility Tests

        /// <summary>
        /// This piece of code exercises a component's ability to assume two closely-related responsibilities ("Accept message" and "Store message").
        /// It simply checks that an expected change of state has occured as the result of a call to a specific method.
        /// </summary>
        [Test]
        public void BufferedChannelQueue_AcceptsAndStoresMessage()
        {
            IMessageQueue bufferedChannelQueue = new ResponsibilitiesExample.ResponsibilityFocused.BufferedChannelQueue(new MessageChannel("Channel #1"), _QUEUE_CAPACITY);

            // Confirm that BufferedChannelQueue is capable of accepting and storing a message
            bufferedChannelQueue.PutMessage(new Message("Test Message"));

            Assert.AreEqual(1, bufferedChannelQueue.MessageCount);
        }

        #endregion

        #region Collaboration Tests

        #region Forward Messages When Queue Reaches Capacity

        /// <summary>
        /// This test "asks" the object under test about it's internal state in order to confirm that some responsibility has been carried-out.
        /// It is not a "true" behaviour test, and as such: -
        /// 
        ///     - The test cannot be sure that the object's state did not change as a side-effect of some other internal behaviour.
        ///     - The demand for the object to expose some internal state in order to facilitate a behaviour test may be an example of YAGNI.
        ///     
        /// </summary>
        [Test]
        public void BufferedChannelQueue_PurgesMessages_WhenQueueReachesCapacity()
        {
            IMessageQueue bufferedChannelQueue = new ResponsibilitiesExample.ResponsibilityFocused.BufferedChannelQueue(new MessageChannel("Channel #1"), _QUEUE_CAPACITY);

            IMessage message = new Message("Message #1");
            bufferedChannelQueue.PutMessage(message);

            message = new Message("Message #2");
            bufferedChannelQueue.PutMessage(message);

            message = new Message("Message #3");
            bufferedChannelQueue.PutMessage(message);

            Assert.AreEqual(0, bufferedChannelQueue.MessageCount);
        }

        /// <summary>
        /// This test does not rely on "asking" the state of the object under test, but instead uses mocks to confirm that the object behaves as expected.
        /// As such, it is a "true" behaviour test that makes no other demands on the object (such as exposing the "MessageCount" property) other than to
        /// carry-out it's responsibility.
        /// </summary>
        [Test]
        public void BufferedChannelQueue_ForwardsAllMessages_WhenQueueReachesCapacity()
        {
            #region Expectations

            // Expect BufferedChannelQueue to forward all messages by calling IMessageChannel.PutMessage() three times.

            IMessageChannel messageChannel = _mocks.DynamicMock<IMessageChannel>();           
            IMessage message = new Message("Test Message");

            messageChannel.PutMessage(message);
            LastCall.Repeat.Times(_QUEUE_CAPACITY);

            _mocks.ReplayAll();

            #endregion

            IMessageQueue bufferedChannelQueue = new ResponsibilitiesExample.ResponsibilityFocused.BufferedChannelQueue(messageChannel, _QUEUE_CAPACITY);

            bufferedChannelQueue.PutMessage(message);
            bufferedChannelQueue.PutMessage(message);
            bufferedChannelQueue.PutMessage(message);
        }

        #endregion

        #endregion
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior) Oculo Consulting Limited
United Kingdom United Kingdom
Matthew Cannon is a software developer and architect who has for the last 10 years focused on object-oriented design. His areas of interest are OOD, patterns, Agile practices, C# and all things .Net.

Comments and Discussions