Charu
Charu

Reputation: 2717

How to stub out the dependency in a static class?

I have a static class wherein I am reading an XML to build a dictionary. Now this initialization is done in the static constructor.

In order to test this Initialize method, I have to somehow stub out the reading of XML logic and just give it an XDocument for testing, but not sure how can I do that.

 internal static class MasterMnemonicsLookup
    {

        private static Dictionary<string, StateCoverageMnemonic[]> masterMnemonics = new Dictionary<string, StateCoverageMnemonic[]>();


        private static StateCoverageMnemonic[] stateCoverageMnemonics;



        static MasterMnemonicsLookup()
        {
            Initialize();
        }

        private static void Initialize()
        {
            var resource = XDocument.Parse(GetResourceTextFile("MasterMnemonics.xml"));
            var serializer = new XmlSerializer(typeof (MasterMnemonicsType));
            var model = (MasterMnemonicsType) serializer.Deserialize(resource.CreateReader());

            var stateCoverageMnemonicsList = new List<StateCoverageMnemonic>();
            foreach (var masterMnemonic in model.MasterMnemonics)
            {
                var stateCoverageMnemonicsXml = new List<StateCoverageMnemonic>();

                var excludedStates = RiskStates.None;
                StateCoverageMnemonic allStateCoverageMnemonic = null;
                foreach (var stateCoverageMnemonic in masterMnemonic.StateCoverageMnemonics)
                {
                    var state = stateCoverageMnemonic.StateCode;
                    if (!state.HasFlag(RiskStates.All))
                    {
                        excludedStates = excludedStates | state;
                        var mnemonic = stateCoverageMnemonic.Mnemonic;
                        var coverageCode = stateCoverageMnemonic.CoverageCode;
                        var stateCoverageMnemonicTemp = new StateCoverageMnemonic(state, mnemonic, coverageCode);
                        stateCoverageMnemonicsXml.Add(stateCoverageMnemonicTemp);
                    }
                    else
                    {
                        //// TODO: If All occurs twice should we throw an exception
                        allStateCoverageMnemonic = new StateCoverageMnemonic(state, stateCoverageMnemonic.Mnemonic, stateCoverageMnemonic.CoverageCode);
                    }
                }

                if (allStateCoverageMnemonic != null)
                {
                    stateCoverageMnemonicsXml.Add(new StateCoverageMnemonic(RiskStates.All ^ excludedStates, allStateCoverageMnemonic.Mnemonic, allStateCoverageMnemonic.CoverageCode));
                }

                stateCoverageMnemonicsList.AddRange(stateCoverageMnemonicsXml);
                masterMnemonics.Add(masterMnemonic.MasterMnemonic, stateCoverageMnemonicsXml.ToArray());
            }

            stateCoverageMnemonics = stateCoverageMnemonicsList.ToArray();
        }

        private static string GetResourceTextFile(string filename)
        {
            string result = string.Empty;

            using (Stream stream = typeof(MasterMnemonicsLookup).Assembly.GetManifestResourceStream("Geico.Applications.Business.CoverageApi.DomainLayer.DataLayer." + filename))
            {
                var streamReader = new StreamReader(stream);
                result = streamReader.ReadToEnd();
            }
            return result;
        }
    }

Upvotes: 0

Views: 190

Answers (2)

dharshana jagoda
dharshana jagoda

Reputation: 430

I agree with Darious Vaughan-Scott

But if you want to keep using the static constructor you may want to put the loading logic into a seperate class which makes it easier to test.

For example

      internal class MasterMnemonicsLoader
      {
        public void Load(
            XDocument resource,
            Dictionary<string, StateCoverageMnemonic[]> masterMnemonics,
            StateCoverageMnemonic[] stateCoverageMnemonics)
        {
            //Do the loading here

        }
    }

and in the Initialize method you can call the Load method

 private static void Initialize()
 {
    var resource = XDocument.Parse(GetResourceTextFile("MasterMnemonics.xml"));
    var loader = MasterMnemonicsLoader();
    loader.Load(resource, masterMnemonics, stateCoverageMnemonics);

Upvotes: 0

DvS
DvS

Reputation: 1095

Using static contructors in this way is not advised, and your scenario is a good example why. You might try the singleton pattern using a public instance constructor that accepts an XDocument. (You can use internal, but this makes it harder to unit test). This is a simple form of dependency injection.

For testing, an instance of your class can simply be created by your testing framework with the test XDocument.

For your live application, a static instance of your class can be initialized and held by a container type, and the appropriate XDocument can be passed in privately (within the container).

Upvotes: 2

Related Questions