title: Faking a INI Configuration File Settings with FakeItEasy in C#
body: <p>I have a class that inherits from the abstract Configuration class, and then each class implements the reader for INI files, XML, conf, or proprietary formats.  I am having a problem in creating the objects to be tested using FakeItEasy.</p>
  
  <p>The object I am trying to test uses the configuration object via Dependency Injection, so it can simply read configuration settings by calling the ReadString(), ReadInteger() etc... functions, and then the text for the location (Section, Key for instance, with an INI) may be retrieved from the appropriate section in whatever format of configuration file (INI, XML, conf, etc...).  </p>
  
  <p>Sample code being used:</p>
  
  <pre><code>public class TestFile
  {
      private readonly ConfigurationSettings ConfigurationController_ ;
  
      ...
  
      public TestFile(ConfigurationSettings ConfigObject)
      {
          this.ConfigurationController_ = ConfigObject;
      }
  
      public TestFile(XMLFile ConfigObject)
      {
          this.ConfigurationController_ = ConfigObject;
      }
  
      public TestFile(INIFile ConfigObject)
      {
          this.ConfigurationController_ = ConfigObject;
      }
  
      ...
  
      private List&lt;string&gt; GetLoginSequence()
      {
          List&lt;string&gt; ReturnText = new List&lt;string&gt;();
          string SignOnFirst = ConfigurationController_.ReadString("SignOn", "SignOnKeyFirst", "Y");
          string SendEnterClear = ConfigurationController_.ReadString("SignOn", "SendEnterClear", "N");
  
          if (SendEnterClear.Equals("Y", StringComparison.CurrentCultureIgnoreCase))
          {
              ReturnText.Add("enter");
              ReturnText.Add("clear");
          }
  
          if (SignOnFirst.Equals("N", StringComparison.CurrentCultureIgnoreCase))
          {
              ReturnText.AddRange(MacroUserPassword("[$PASS]"));
              ReturnText.Add("sign_on");
          }
          else
          {
              ReturnText.Add("sign_on");
              ReturnText.AddRange(MacroUserId("[$USER]"));
              ReturnText.AddRange(MacroUserPassword("[$PASS]"));
          }
          return ReturnText;
      }
  </code></pre>
  
  <p>A Simple Test example:</p>
  
  <pre><code>    [TestMethod]
      public void TestSignOnSequence()
  
          IniReader FakeINI = A.Fake&lt;IniReader&gt;();
  
          //Sample Reads:
          //Config.ReadString("SignOn", "SignOnKeyFirst", "Y");
          //Config.ReadString("SignOn", "SendEnterClear", "N");  // Section, Key, Default
  
          A.CallTo(() =&gt; FakeINI.ReadString(A&lt;string&gt;.That.Matches(s =&gt; s == "SignOn"), A&lt;string&gt;.That.Matches(s =&gt; s == "SendEnterClear"))).Returns("N");
          A.CallTo(() =&gt; FakeINI.ReadString(A&lt;string&gt;.That.Matches(s =&gt; s == "SignOn"), A&lt;string&gt;.That.Matches(s =&gt; s == "SignOnKeyFirst"))).Returns("N");
  
          A.CallTo(FakeINI).Where( x =&gt; x.Method.Name == "ReadInteger").WithReturnType&lt;int&gt;().Returns(1000);
  
          TestFile TestFileObject = new TestFile(FakeINI);
  
          List&lt;string&gt; ReturnedKeys = TestFileObject.GetLoginSequence();
          Assert.AreEqual(2, ReturnedKeys.Count, "Ensure all keystrokes are returned");
  </code></pre>
  
  <p>This compiles fine, but when I execute the code, I get the following Exception:</p>
  
  <pre><code>Test threw Exception:
  FakeItEasy.Configuration.FakeConfigurationException:
      The current proxy generator can not intercept the specified method for the following reason:
      - Non virtual methods can not be intercepted.
  </code></pre>
  
  <p>If I change how I create the fake which then works without an exception, I can not get different values for the various calls to the same function.</p>
  
  <pre><code>A.CallTo(FakeINI).Where( x =&gt; x.Method.Name == "ReadString").WithReturnType&lt;string&gt;().Returns("N");
  </code></pre>
  
  <p>The above method does not allow me to control the return for the different calls that the function uses to the INI.  </p>
  
  <p>How can I combine the two methods, the where and the test of the parameters?</p>
  
  <p>Additional definitions as requested:</p>
  
  <pre><code>public abstract class ConfigurationSettings
  {
      ...
  
      abstract public int ReadInteger(string Section, string Key, int Default);
      abstract public string ReadString(string Section, string Key, string Default);
  
      public int ReadInteger(string Section, string Key)
      {   return ReadInteger(Section, Key, 0);    }
  
      public int ReadInteger(string Key, int Default)
      {   return ReadInteger("", Key, Default);   }
  
      public int ReadInteger(string Key)
      {   return ReadInteger(Key, 0);             }
  
      public string ReadString(string Section, string Key)
      {   return ReadString(Section, Key, null);  }
  }
  
  public class IniReader : ConfigurationSettings
  {
      ...
  
      public IniReader()
      {
      }
  
      public IniReader(string PathAndFile) 
      {
          this.PathAndFileName = PathAndFile;
      }
  
      public override int ReadInteger(string Section, string Key, int Default)
      {
          return GetPrivateProfileInt(Section, Key, Default, PathAndFileName);
      }
  
      public override string ReadString(string Section, string Key, string Default)
      {
          StringBuilder WorkingString = new StringBuilder(MAX_ENTRY);
          int Return = GetPrivateProfileString(Section, Key, Default, WorkingString, MAX_ENTRY, PathAndFileName);
          return WorkingString.ToString();
      }
  }
  </code></pre>