कॉन्फ़िगरेशन को कैसे प्रबंधित करें


123

मैं कोड के इस बिंदु पर अटक गया हूं कि मुझे नहीं पता कि कैसे मज़ाक करना है:

ConfigurationManager.AppSettings["User"];

मुझे कॉन्फ़िगरेशन प्रबंधक का मजाक उड़ाना है, लेकिन मेरे पास कोई सुराग नहीं है, मैं Moq का उपयोग कर रहा हूं ।

कोई मुझे टिप दे सकता है? धन्यवाद!

जवाबों:


103

मेरा मानना ​​है कि इसके लिए एक मानक दृष्टिकोण कॉन्फ़िगरेशन प्रबंधक को लपेटने के लिए एक मुखौटा पैटर्न का उपयोग करना है और फिर आपके पास कुछ शिथिल युग्मित है जो आपके पास नियंत्रण है।

तो आप कॉन्फ़िगरेशन प्रबंधक को लपेटेंगे। कुछ इस तरह:

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

(आप बस अपने विन्यास वर्ग से एक अंतरफलक निकाल सकते हैं और फिर अपने कोड में हर जगह उस इंटरफ़ेस का उपयोग कर सकते हैं) फिर आप सिर्फ IConfiguration का मजाक उड़ाते हैं। आप स्वयं को कुछ अलग तरीकों से लागू करने में सक्षम हो सकते हैं। ऊपर मैंने केवल व्यक्तिगत गुणों को लपेटने के लिए चुना। आप कमजोर टाइप किए गए हैश सरणियों के बजाय काम करने के लिए दृढ़ता से टाइप की गई जानकारी प्राप्त करने का पक्ष लाभ प्राप्त करते हैं।


6
यह वैचारिक रूप से मैं भी कर रहा हूं। हालांकि, मैं कैसल डिक्शनरी एडेप्टर ( कैसल कोर का हिस्सा ) का उपयोग करता हूं जो मक्खी पर इंटरफेस के कार्यान्वयन को उत्पन्न करता है। मैंने इसके बारे में कुछ समय पहले लिखा है: blog.andreloker.de/post/2008/09/05/… (नीचे स्क्रॉल करके "A Solution" देखें कि मैं कैसे कैसल डिक्शनरी एडेप्टर का उपयोग करता हूं)
आंद्रे लोकर

यह निफ्टी है और यह एक अच्छा लेख है। मुझे भविष्य के लिए इसे ध्यान में रखना होगा।
जोशुआ एनफील्ड

मैं आपकी शुद्धतावाद और व्याख्याओं के आधार पर भी जोड़ सकता हूं - इसके बजाय इसे एक प्रतिनिधि प्रॉक्सी या एडाप्टर भी कहा जा सकता है।
यहोशू एनफील्ड

3
ऊपर से यह Moq को "सामान्य" के रूप में उपयोग कर रहा है। अनटाइटेड, लेकिन कुछ इस तरह: var configurationMock = new Mock<IConfiguration>();और सेटअप के लिए:configurationMock.SetupGet(s => s.User).Returns("This is what the user property returns!");
जोशुआ एनफील्ड

इस परिदृश्य का उपयोग तब किया जाता है जब एक परत IConfiguration पर निर्भर होती है और आपको IConfiguration को मॉक करने की आवश्यकता होती है, लेकिन आप IConfiguration कार्यान्वयन को कैसे परखेंगे? और अगर आप एक यूनिट टेस्ट कॉन्फिगरेशन मेनेजर.ऐपसेटिंग ["यूजर"] में कॉल करते हैं, तो यह यूनिट का परीक्षण नहीं करेगा, लेकिन यह परीक्षण करेगा कि कॉन्फ़िगरेशन फ़ाइल से कौन से मान प्राप्त होते हैं, जो कि यूनिट टेस्ट नहीं है। यदि आपको कार्यान्वयन की जांच करने की आवश्यकता है, तो @ zpbappi.com/testing-codes-with-configurationmanager-appsettings
nkalfov

173

मैं AspnetMvc4 का उपयोग कर रहा हूं। एक क्षण पहले मैंने लिखा था

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

मेरे परीक्षण विधि में और यह पूरी तरह से काम किया।

स्पष्टीकरण: परीक्षण विधि आम तौर पर web.configया से ली गई ऐप सेटिंग्स के संदर्भ में चलती है myapp.configConfigurationsManagerइस एप्लिकेशन-ग्लोबल ऑब्जेक्ट तक पहुँच सकते हैं और इसमें हेरफेर कर सकते हैं।

यद्यपि: यदि आपके पास समानांतर में एक परीक्षण धावक चल रहा है तो यह एक अच्छा विचार नहीं है।


8
यह समस्या को हल करने के लिए वास्तव में चतुर और सरल तरीका है! सादगी के लिए यश!
नवाप

1
ज्यादातर मामलों में एक अमूर्त बनाने की तुलना में बहुत आसान है
माइकल क्लार्क

2
बस???? दीप्ति सादगी में है क्योंकि मैं इस विशेष सीलबंद वर्ग का परीक्षण करने के बारे में अपने दिमाग को लगा रहा था।
पायोत्र कुला

5
ConfigurationManager.AppSettingsएक NameValueCollectionऐसा धागा है जो सुरक्षित नहीं है, इसलिए सम्यक तुल्यकालन के बिना इसका उपयोग करते हुए समानांतर परीक्षण वैसे भी अच्छा विचार नहीं है। अन्यथा आप सिर्फ ConfigurationManager.AppSettings.Clear()अपने TestInitialize/ ctor में कॉल कर सकते हैं और आप सुनहरे हो सकते हैं।
ओहद श्नाइडर

1
सरल और संक्षिप्त। अब तक का सबसे अच्छा जवाब!
znn

21

शायद वह नहीं है जिसे आपको पूरा करने की आवश्यकता है, लेकिन क्या आपने अपने परीक्षण प्रोजेक्ट में app.config का उपयोग करने पर विचार किया है? तो विन्यास प्रबंधक को वे मान मिलेंगे जो आप app.config में डालते हैं और आपको कुछ भी मॉक करने की आवश्यकता नहीं है। यह समाधान मेरी आवश्यकताओं के लिए अच्छा काम करता है, क्योंकि मुझे कभी भी "चर" कॉन्फ़िगरेशन फ़ाइल का परीक्षण करने की आवश्यकता नहीं होती है।


7
यदि कॉन्फ़िगरेशन मान के आधार पर परीक्षण परिवर्तनों के तहत कोड का व्यवहार, यह सीधे परीक्षण करने के लिए आसान है अगर यह सीधे AppSettings पर निर्भर नहीं करता है।
आंद्रे लॉकर

2
यह बुरा अभ्यास है क्योंकि आप अन्य संभावित सेटिंग्स का कभी परीक्षण नहीं कर रहे हैं। परीक्षण के लिए जोशुआ एनफील्ड का जवाब बहुत अच्छा है।
mkaj

4
जबकि अन्य इस जवाब के खिलाफ हैं, मैं कहूंगा कि उनकी स्थिति थोड़ी सामान्य है। यह कुछ परिदृश्यों में बहुत ही मान्य उत्तर है और यह वास्तव में सिर्फ इस बात पर निर्भर करता है कि आपको क्या चाहिए। उदाहरण के लिए, मान लें कि मेरे पास 4 अलग-अलग क्लस्टर हैं, जिनमें से प्रत्येक का आधार URL है। उन 4 समूहों को Web.configप्रोजेक्ट के दौरान, रनटाइम के दौरान, खींचा जाता है । परीक्षण के दौरान, कुछ ज्ञात मूल्यों को खींचना app.configबहुत ही मान्य है। इकाई परीक्षण को यह सुनिश्चित करने की आवश्यकता है कि जब पुल "क्लस्टर 1" काम करता है, तो शर्तों को सुनिश्चित करना चाहिए; इस मामले में केवल 4 अलग-अलग क्लस्टर हैं।
माइक पेर्रेनौड

14

आप 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 फेक के साथ शिमले और फेक के बारे में, आइसोलेटिंग कोड अंडर टेस्ट के बारे में अधिक पढ़ सकते हैं । उम्मीद है की यह मदद करेगा।


6
लेखक एमएस फेक के बारे में नहीं, moq के साथ कैसे के लिए पूछ रहा है।
जेपीसीएफ

6
और यह कैसे अलग है? यह उसके कोड से डेटा निर्भरता को हटाकर मॉकिंग को प्राप्त करता है। C # Fakes का उपयोग करना एक दृष्टिकोण है!
जोरावर

9

क्या आपने मजाक करने के बजाय ठूंठ माना है? 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 पर निर्भरता नहीं है जब तक कि आपको वास्तव में इसकी आवश्यकता न हो।


3
मुझे यह तरीका सबसे अच्छा लगता है। एक तरफ, IConfigurationजोशुआ एनफील्ड के रूप में कॉन्फ़िगरेशन प्रबंधक को लपेटने से पता चलता है कि यह बहुत उच्च स्तर का हो सकता है, और आपको खराब कॉन्फ़िगरेशन मान पार्सिंग जैसी चीजों के कारण मौजूद कीड़े याद आ सकते हैं। दूसरी ओर, ConfigurationManager.AppSettingsलॉसमैनोस के रूप में सीधे उपयोग करने से पता चलता है कि यह कार्यान्वयन विवरण का बहुत अधिक है, इसका उल्लेख नहीं करने के लिए अन्य परीक्षणों पर दुष्प्रभाव हो सकते हैं और मैन्युअल सिंक्रनाइज़ेशन के बिना समानांतर परीक्षण रन में उपयोग नहीं किया जा सकता है (जैसा NameValueConnectionकि थ्रेड सुरक्षित नहीं है)।
ओहद श्नाइडर

2

यह एक स्थिर संपत्ति है, और Moq Moq उदाहरण के तरीकों या वर्गों के लिए डिज़ाइन किया गया है जो विरासत के माध्यम से मज़ाक उड़ाया जा सकता है। दूसरे शब्दों में, Moq आपके यहाँ कोई मदद करने वाला नहीं है।

स्टैटिक्स का मज़ाक उड़ाने के लिए, मैं मोल्स नामक एक उपकरण का उपयोग करता हूं , जो मुफ़्त है। अन्य फ्रेमवर्क अलगाव उपकरण हैं, जैसे टाइपमॉक जो ऐसा कर सकते हैं, हालांकि मेरा मानना ​​है कि वे भुगतान किए गए उपकरण हैं।

जब यह स्टैटिक्स और परीक्षण की बात आती है, तो एक और विकल्प स्वयं स्टेटिक स्टेट बनाना है, हालांकि यह अक्सर समस्याग्रस्त हो सकता है (जैसे, मुझे लगता है कि यह आपके मामले में होगा)।

और, अंत में, यदि आइसोलेशन फ्रेमवर्क एक विकल्प नहीं है और आप इस दृष्टिकोण के लिए प्रतिबद्ध हैं, तो यहोशू द्वारा उल्लिखित मुखौटा एक अच्छा तरीका है, या सामान्य रूप से कोई भी दृष्टिकोण जहां आप इस व्यापार के तर्क से दूर ग्राहक कोड है कि आप परीक्षण करने के लिए उपयोग कर रहे हैं।


1

मुझे लगता है कि आप अपना खुद का ऐप लिखना चाहते हैं ।config प्रदाता एक सरल काम है और फिर कुछ और उपयोगी है। विशेष रूप से आपको शिम आदि जैसे किसी भी फेक से बचना चाहिए क्योंकि जैसे ही आप उन्हें एडिट करते हैं और काम नहीं करते हैं।

मेरे द्वारा उपयोग किए जाने वाले प्रदाता इस तरह दिखते हैं:

डिफ़ॉल्ट रूप से उन्हें मान मिलते हैं App.configलेकिन यूनिट परीक्षणों के लिए मैं सभी मूल्यों को ओवरराइड कर सकता हूं और प्रत्येक परीक्षण में स्वतंत्र रूप से उनका उपयोग कर सकता हूं।

किसी भी इंटरफेस की आवश्यकता नहीं है या इसे बार-बार लागू करना है। मेरे पास एक यूटिलिटी डीएल है और इस छोटे हेल्पर का उपयोग कई परियोजनाओं और यूनिट परीक्षणों में किया जाता है।

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; } }
}

1

कैसे बस के बारे में क्या आप की जरूरत है? क्योंकि, मैं .NET का मजाक नहीं उड़ाना चाहता, क्या मैं ...?

System.Configuration.ConfigurationManager.AppSettings["myKey"] = "myVal";

आपको शायद पहले से ही AppSettings को साफ करना चाहिए ताकि यह सुनिश्चित हो सके कि ऐप केवल वही देखता है जो आप इसे चाहते हैं।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.