7

I have created a custom ConfigurationElement and ConfigurationSection to make it easier to set up a host of application parameters at startup. However, I'd really like to unit test this logic.

ServiceConnection

public class ServiceConnection : ConfigurationElement
{
    [ConfigurationProperty("locationNumber", IsRequired = true)] 
    public string LocationNumber
    {
        get { return (string) base["locationNumber"]; }
        set { base["locationNumber"] = value; }
    }

    [ConfigurationProperty("hostName", IsRequired = true)]
    public string HostName
    {
        get { return (string) base["hostName"]; }
        set { base["hostName"] = value; }
    }

    [ConfigurationProperty("port", IsRequired = true)]
    public int Port
    {
        get { return (int) base["port"]; }
        set { base["port"] = value; }
    }

    [ConfigurationProperty("environment", IsRequired = true)]
    public string Environment
    {
        get { return (string) base["environment"]; }
        set { base["environment"] = value.ToUpper(); }
    }

    internal string Key
    {
        get { return string.Format("{0}|{1}", LocationNumber, Environment); }
    }
}

ServiceConnection Collection

[ConfigurationCollection(typeof(ServiceConnection), AddItemName = "service", CollectionType = ConfigurationElementCollectionType.BasicMap)]
public class ServiceConnectionCollection : ConfigurationElementCollection
{
    protected override ConfigurationElement CreateNewElement()
    {
        return new ServiceConnection();
    }

    protected override object GetElementKey(ConfigurationElement element)
    {
        return ((ServiceConnection) element).Key;
    }

    public ServiceConnection Get(string locationNumber, string environment = "PRODUCTION")
    {
        return (ServiceConnection) BaseGet(string.Format("{0}|{1}", locationNumber, environment));
    }

    public ServiceConnection this[int index]
    {
        get { return (ServiceConnection)BaseGet(index); }
        set
        {
            if (BaseGet(index) != null)
            {
                BaseRemoveAt(index);
            }
            BaseAdd(index, value);
        }
    }
}

Some Test XML

<MyServiceConnections>
    <service locationNumber="0AB0" hostName="DEVSERVER" port="1234" environment="DEVELOPMENT" />
    <service locationNumber="0AB0" hostName="BETASERVER" port="1234" environment="BETA" />
    <service locationNumber="0AB0" hostName="PRODSERVER" port="1234" environment="PRODUCTION" />
</MyServiceConnections>

In my production code, I'm using ConfigurationManager to retrieve the ServiceConnection but am not sure how to create a test that bypasses the manager altogether.

I'm looking to retrieve a ServiceConnection object and make sure all the fields match the input that I set up in the test XML. I'd also like to test functionality when a user failed to populate one or more of the fields.

Killnine
  • 5,728
  • 8
  • 39
  • 66
  • Can you explain what exactly you want to test? I would extract the ConfigurationManager code from the actual implementation and inject that. – CodeCaster Aug 14 '14 at 13:08
  • @CodeCaster: Edited. "I'm looking to retrieve a ServiceConnection object and make sure all the fields match the input that I set up in the test XML. I'd also like to test functionality when a user failed to populate one or more of the fields." I've used this code in another project some time ago and ran into issues on the build server (TeamCity) when running against the live App.config and trying to use `ConfigurationManager`. I'd like to bypass it entirely, if possible. Not sure if an `XmlReader` is the right track. – Killnine Aug 14 '14 at 13:18
  • 1
    http://stackoverflow.com/questions/15133379/how-to-test-custom-configuration-section-in-web-config? – CodeCaster Aug 14 '14 at 13:29
  • A way to test without ConfigurationManager.GetSection (and configuration by file) using an adapted section constructor taking string as argument: https://stackoverflow.com/a/704817/954701 – Henrik Feb 26 '18 at 09:05

1 Answers1

11

Well, I ended up simply going with what @CodeCaster suggested and using ConfigurationManager anyway (as suggested by his link here).

I've posted a sample test below:

[Test]
public void ShouldProvideFullProductionServiceConnectionRecord()
{
    //NOTE: Open ConfigTests.config in this project to see available ServiceConnection records

    //Arrange
    ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap { ExeConfigFilename = "ConfigTests.config" };
    Configuration config = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);

    ServiceConnectionSection section = config.GetSection("AutomationPressDataCollectionServiceConnections") as ServiceConnectionSection;

    //Act
    var productionSection = section.Connections.Get("0Q8");

    //Assert
    Assert.AreEqual("0AB0", productionSection.LocationNumber);
    Assert.AreEqual("DEVSERVER", productionSection.HostName);
    Assert.AreEqual(1234, productionSection.Port);
    Assert.AreEqual("DEVELOPMENT", productionSection.Environment);
}

It requires you add a new .Config file and set its output as Content and set to Copy if Newer (it's in a unit test project). But it's better than having no coverage at all.

Community
  • 1
  • 1
Killnine
  • 5,728
  • 8
  • 39
  • 66