0

I have a class in which there is a parameter less constructor. But when this constructor is called, there are five properties of the class that gets values from config file in the constructor. There are two method in the class which uses the parameters that get initialized in the constructor.

I want to write unit test for two methods using mock framework. But, I am not sure of how to initialize the parameters in the constructor as calling the method will not provide the value to those properties.

public class ABC
{
   public ABC()
   {
      a = ConfigurationManager.AppSetting["GetValue"];
      b = ConfigurationManager.AppSetting["GetValue1"];
   }

   public int Method1(IDictionary<string, string> dict)
   {
      d = a + b /2; (how to mock values of a and b while writing unit tests 
                     using mock framework. In reality, a in my case is 
                     dictionary)

//some business logic

      return d;
   }
}

Thanking in advance,

Vijayanath Viswanathan
  • 8,027
  • 3
  • 25
  • 43
Vicky
  • 624
  • 2
  • 12
  • 35
  • There is no mocking as the constructor tightly coupled to `ConfigurationManager` You could however add the needed key/value pairs to the app.config of the unit test. Can't say much more given how sparse the provided information is. Provider a [mcve] that can be used to replicate the actual problem and aid in constructing a possible solution – Nkosi Aug 28 '17 at 10:53
  • Use a wrapper around configurationmanager and mock the wrapper type. See [here](https://stackoverflow.com/questions/9486087/how-to-mock-configurationmanager-appsettings-with-moq) – Nilesh Aug 28 '17 at 19:43

1 Answers1

9

You cannot Mock values of a and b as your code is tightly coupled with app.config file. You can create an interface. Refactor code like below to inject an interface to you constructor and then mock it,

 public class ABC
    {
        private int a;
        private int b;
        public ABC(IConfig config)
        {
            a = config.a;
            b = config.b;
        }

        public int Method1(IDictionary<string, string> dict)
        {
            int d = a + b / 2;

            return d;
        }
    }

    public interface IConfig
    {
        int a { get; }
        int b { get; }
    }
    public class Config : IConfig
    {
        public int a => Convert.ToInt32(ConfigurationManager.AppSettings["GetValue"]);
        public int b => Convert.ToInt32(ConfigurationManager.AppSettings["GetValue1"]);
    }

And in you test class Mock and inject IConfig like below,

Mock<IConfig> _mockConfig = new Mock<IConfig>();

        _mockConfig.Setup(m => m.a).Returns(1);
        _mockConfig.Setup(m => m.b).Returns(2);

        ABC abc = new ABC(_mockConfig.Object);

Now your code is decoupled with app.config and you will get mock values of a and b while running unit test.

Vijayanath Viswanathan
  • 8,027
  • 3
  • 25
  • 43