Lazy/Poor Man’s IOC

17. February 2016 11:47

There may be times where you need IOC for nothing more than the ability to mock something for testing. In these cases you may not want to bother with all the configuration of a real IOC implementation. This ‘poor man’s’ methodology I’ve used could probably be frowned upon but it does what I need it to do in most cases (there will be use cases where this will not work).

 

The basic idea is to have either a publicly settable property or a constructor param for the concrete implementation. Then in the property getter if the backing field is null, create the ‘real’ implementation.  This allows the test cases to either set the property to a mock or pass a mock into the constructor.

 

Given these members of a controller class:

 

 

        private IConfigAccess _configDatAccess;

        private IPciMasker _pciMasker;

        private object _lock = new object();

 

        public IConfigAccess ConfigDataAccess

        {

            get

            {

                lock(_lock)

                {

                    if (_configDatAccess == null) _configDatAccess = new ConfigAccessService();

                }

                return _configDatAccess;

            }

            set

            {

                _configDatAccess = value;

            }

        }

 

        public IPciMasker PciMasker

        {

            get

            {

                lock (_lock)

                {

                    if (_pciMasker == null) _pciMasker = new PciMasker();

                }

                return _pciMasker;

            }

            set

            {

                _pciMasker = value;

            }

        }

In the unit test where you want to mock the IConfigAccess member just set the ConfigDataAccess property to the mocked object and run the test:

 

            var dacMock = new Mock<IConfigAccess>();

            dacMock.Setup(x => x.GetPciMaskByEntryPointId(epId)).Returns(GetDefaultMaskList());

 

            var controller = new ChatConversationController();

            controller.ConfigDataAccess = dacMock.Object;

           

            controller.NewMessage(item);

           

            Assert.AreEqual(expected, item.Message);

 

You just have to make sure to use the property and not the backing field. But don’t worry. If you forget a null reference exception will remind you in a hurry!

About the author

I'm a .NET developer, a husband and a father of three beautiful girls.

Month List