program story

moq로 ConfigurationManager.AppSettings를 조롱하는 방법

inputbox 2020. 7. 26. 13:02
반응형

moq로 ConfigurationManager.AppSettings를 조롱하는 방법


조롱하는 방법을 모르는이 코드 지점에 갇혀 있습니다.

ConfigurationManager.AppSettings["User"];

ConfigurationManager를 조롱해야하지만 단서가 없으며 Moq 사용하고 있습니다.

누군가 나에게 팁을 줄 수 있습니까? 감사!


이것에 대한 하나의 표준 접근법은 파사드 패턴 을 사용 하여 구성 관리자를 래핑하고 느슨하게 결합 된 것을 제어하는 ​​것입니다.

따라서 ConfigurationManager를 래핑합니다. 다음과 같은 것 :

public class Configuration: IConfiguration
{
    public User
    {
        get{ 
               return ConfigurationManager.AppSettings["User"];
       }
    }
}

(구성 클래스에서 인터페이스를 추출한 다음 코드의 어느 곳에서나 해당 인터페이스를 사용할 수 있습니다) 그런 다음 IConfiguration을 조롱합니다. 몇 가지 다른 방식으로 파사드 자체를 구현할 수 있습니다. 위에서 나는 개별 속성을 감싸기로 선택했습니다. 또한 약한 유형의 해시 배열이 아닌 강력한 유형의 정보를 사용하여 얻을 수있는 부수적 인 이점을 얻을 수 있습니다.


AspnetMvc4를 사용하고 있습니다. 얼마 전에 나는 썼다

ConfigurationManager.AppSettings["mykey"] = "myvalue";

내 테스트 방법에서 완벽하게 작동했습니다.

설명 : 테스트 방법은 일반적으로 web.config또는 에서 가져온 앱 설정이 포함 된 컨텍스트에서 실행됩니다 myapp.config. ConfigurationsManager이 응용 프로그램 전역 객체에 도달하여 조작 할 수 있습니다.

비록 테스트 러너가 테스트를 병렬로 실행하고 있다면 이것은 좋은 생각이 아닙니다.


어쩌면 달성해야 할 것이 아니지만 테스트 프로젝트에서 app.config 사용을 고려한 적이 있습니까? 따라서 ConfigurationManager는 app.config에 입력 한 값을 가져 오므로 아무것도 조롱 할 필요가 없습니다. 이 솔루션은 "가변"구성 파일을 테스트 할 필요가 없기 때문에 내 요구에 적합합니다.


심을 사용 AppSettings하여 사용자 정의 NameValueCollection객체 를 수정할 수 있습니다 . 이를 달성하는 방법의 예는 다음과 같습니다.

[TestMethod]
public void TestSomething()
{
    using(ShimsContext.Create()) {
        const string key = "key";
        const string value = "value";
        ShimConfigurationManager.AppSettingsGet = () =>
        {
            NameValueCollection nameValueCollection = new NameValueCollection();
            nameValueCollection.Add(key, value);
            return nameValueCollection;
        };

        ///
        // Test code here.
        ///

        // Validation code goes here.        
    }
}

심즈 및 위조에 대한 자세한 내용은 Microsoft Fakes로 테스트중인 코드 격리 에서 확인할 수 있습니다 . 도움이 되었기를 바랍니다.


조롱 대신 스터 빙을 고려 했습니까? AppSettings속성은이다 NameValueCollection:

[TestClass]
public class UnitTest1
{
    [TestMethod]
    public void TestMethod1()
    {
        // Arrange
        var settings = new NameValueCollection {{"User", "Otuyh"}};
        var classUnderTest = new ClassUnderTest(settings);

        // Act
        classUnderTest.MethodUnderTest();

        // Assert something...
    }
}

public class ClassUnderTest
{
    private readonly NameValueCollection _settings;

    public ClassUnderTest(NameValueCollection settings)
    {
        _settings = settings;
    }

    public void MethodUnderTest()
    {
        // get the User from Settings
        string user = _settings["User"];

        // log
        Trace.TraceInformation("User = \"{0}\"", user);

        // do something else...
    }
}

이점은 구현이 더 간단하고 실제로 필요할 때까지 System.Configuration에 대한 종속성이 없다는 것입니다.


That is a static property, and Moq is designed to Moq instance methods or classes that can be mocked via inheritance. In other words, Moq is not going to be any help to you here.

For mocking statics, I use a tool called Moles, which is free. There are other framework isolation tools, like Typemock that can do this too, though I believe those are paid tools.

When it comes to statics and testing, another option is to create the static state yourself, though this can often be problematic (as, I'd imagine it would be in your case).

And, finally, if the isolation frameworks are not an option and you're committed to this approach, the facade mentioned by Joshua is a good approach, or any approach in general where you factor client code of this away from the business logic that you're using to test.


I think writing you own app.config provider is a simple task and is more useful then anything else. Especially you should avoid any fakes like shims etc. because as soon as you use them Edit & Continue no longer works.

The providers I use look like this:

By default they get the values from the App.config but for unit tests I can override all values and use them in each test independently.

There's no need for any interfaces or implement it each time over and over again. I have a utilities dll and use this small helper in many projects and unit tests.

public class AppConfigProvider
{
    public AppConfigProvider()
    {
        ConnectionStrings = new ConnectionStringsProvider();
        AppSettings = new AppSettingsProvider();
    }

    public ConnectionStringsProvider ConnectionStrings { get; private set; }

    public AppSettingsProvider AppSettings { get; private set; }
}

public class ConnectionStringsProvider
{
    private readonly Dictionary<string, string> _customValues = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);

    public string this[string key]
    {
        get
        {
            string customValue;
            if (_customValues.TryGetValue(key, out customValue))
            {
                return customValue;
            }

            var connectionStringSettings = ConfigurationManager.ConnectionStrings[key];
            return connectionStringSettings == null ? null : connectionStringSettings.ConnectionString;
        }
    }

    public Dictionary<string, string> CustomValues { get { return _customValues; } }
}

public class AppSettingsProvider
{
    private readonly Dictionary<string, string> _customValues = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);

    public string this[string key]
    {
        get
        {
            string customValue;
            return _customValues.TryGetValue(key, out customValue) ? customValue : ConfigurationManager.AppSettings[key];
        }
    }

    public Dictionary<string, string> CustomValues { get { return _customValues; } }
}

참고URL : https://stackoverflow.com/questions/9486087/how-to-mock-configurationmanager-appsettings-with-moq

반응형