यूनिट टेस्टिंग के लिए आप C # में फ़ाइल सिस्टम का मज़ाक कैसे उड़ाते हैं?


149

यूनिट टेस्ट लिखने के लिए C # में फ़ाइल सिस्टम को मॉक करने के लिए कोई लाइब्रेरी या मेथड हैं? मेरे वर्तमान मामले में मेरे पास ऐसी विधियाँ हैं जो यह जाँचती हैं कि क्या कुछ फ़ाइल मौजूद है और निर्माण तिथि पढ़ें। मुझे भविष्य में इससे ज्यादा की जरूरत हो सकती है।


1
यह कई अन्य लोगों की नकल की तरह दिखता है, जिनमें शामिल हैं: stackoverflow.com/questions/664277/…
जॉन सॉन्डर्स


2
@ मिच: ज्यादातर समय, यह फ़ाइल सिस्टम में डेटा रखने के लिए पर्याप्त होता है और यूनिट परीक्षणों को अपना कोर्स चलाने देता है। हालाँकि, मैंने ऐसी विधियों का सामना किया है जो कई IO परिचालनों को निष्पादित करती हैं, और इस तरह के तरीकों के लिए परीक्षण वातावरण स्थापित करना एक m1 फ़ाइल सिस्टम का उपयोग करके बहुत सरल है।
स्टीव गाइडी

मैंने उस उद्देश्य (और अधिक) के लिए github.com/guillaume86/VirtualPath लिखा है , यह अभी भी WIP है और एपीआई निश्चित रूप से बदल जाएगा लेकिन यह पहले से ही काम करता है, और कुछ परीक्षण शामिल हैं।
गुइलियम 86

जवाबों:


154

संपादित करें: NuGet पैकेज स्थापित करें System.IO.Abstractions

मूल रूप से स्वीकार किए जाने पर यह पैकेज मौजूद नहीं था। मूल उत्तर नीचे दिए गए ऐतिहासिक संदर्भ के लिए प्रदान किया गया है:

आप एक इंटरफ़ेस बनाकर इसे कर सकते हैं:

interface IFileSystem {
    bool FileExists(string fileName);
    DateTime GetCreationDate(string fileName);
}

और एक 'वास्तविक' कार्यान्वयन का निर्माण करता है जो System.IO.File.Exists () आदि का उपयोग करता है। फिर आप इस इंटरफ़ेस का उपयोग एक नकली रूपरेखा का उपयोग करके कर सकते हैं; मैं Moq की सलाह देता हूं ।

संपादित करें: किसी ने ऐसा किया है और कृपया इसे यहां ऑनलाइन पोस्ट किया है

मैंने इस दृष्टिकोण का उपयोग DateTime.UtcNow को एक IClock इंटरफ़ेस में मॉक करने के लिए किया है (वास्तव में हमारे परीक्षण के लिए वास्तव में उपयोगी है!

एक अन्य दृष्टिकोण टाइपमॉक का उपयोग करना हो सकता है , इससे आप कक्षाओं में कॉल को रोक सकते हैं और उन्हें बाहर निकाल सकते हैं। हालाँकि यह पैसे खर्च करता है, और इसे चलाने के लिए आपकी पूरी टीम के पीसी और आपके बिल्ड सर्वर पर इंस्टॉल करने की आवश्यकता होगी, यह भी जाहिरा तौर पर System.IO.File के लिए काम नहीं करेगा, क्योंकि यह mscorlib को स्टब नहीं कर सकता है

आप बस यह भी स्वीकार कर सकते हैं कि कुछ विधियाँ इकाई परीक्षण योग्य नहीं हैं और एक अलग धीमी गति से चलने वाले एकीकरण / सिस्टम परीक्षण सूट में उनका परीक्षण करती हैं।


1
मेरी राय में, एक इंटरफ़ेस बनाना जैसा कि मैट का वर्णन है कि यहां जाने का रास्ता है। मैंने एक उपकरण भी लिखा है जो आपके लिए ऐसे इंटरफेस उत्पन्न करता है, जो स्टैटिक और / या सीलबंद कक्षाओं, या गैर-नियतात्मक (यानी घड़ियों और रैंडम नंबर जेनरेटर्स) विधियों को मॉक करने के लिए उपयोगी होता है। अधिक जानकारी के लिए jolt.codeplex.com देखें ।
स्टीव गाइडी जूल 6'09

ऐसा लगता है कि संदर्भित लेख में रेपो को बिना सूचना के हटा दिया गया है। हालाँकि, यहाँ इसके प्रयासों का एक नौगट पैकेज प्रतीत होता है: nuget.org/packages/mscorlib-mock
माइक-ई

टाइपमॉक में इस बात पर प्रतिबंध है कि किस प्रकार के फेकेबल हैं (कम से कम वर्तमान संस्करण में अक्टूबर 2017 तक) आप निश्चित रूप से फाइल स्टेटिक क्लास को नकली कर सकते हैं। मैंने खुद इसे सत्यापित किया।
रयान रोडेमेयर

क्या आप कुछ एकीकरण परीक्षण सूट कर सकते हैं?
ओजकॉन

83

संस्थापन-संकुल System.IO.Abstractions

यह काल्पनिक पुस्तकालय अब मौजूद है, System.IO.Abstractions के लिए एक NuGet पैकेज है , जो System.IO नामस्थान को दूर करता है।

परीक्षण सहायकों का एक सेट भी है, System.IO.Abstractions.TestingHelpers जो - लेखन के समय - केवल आंशिक रूप से लागू किया जाता है, लेकिन एक बहुत अच्छा प्रारंभिक बिंदु है।


3
मुझे लगता है कि इस पहले से निर्मित अमूर्त के आसपास मानकीकरण सबसे अच्छा दांव है। उस पुस्तकालय के बारे में कभी नहीं सुना, इसलिए सिर ऊपर करने के लिए बहुत बहुत धन्यवाद।
जूलियागॉन

PM पैकेज मैनेजर के लिए खड़ा है .. खोलने के लिए ... टूल> NuGet पैकेज मैनेजर> पैकेज मैनेजर कंसोल
थ्रेडनोटो

11

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

उदाहरण:

interface IFileWrapper { bool Exists(String filePath); }

class FileWrapper: IFileWrapper
{
    bool Exists(String filePath) { return File.Exists(filePath); }        
}

class FileWrapperStub: IFileWrapper
{
    bool Exists(String filePath) 
    { return (filePath == @"C:\myfilerocks.txt"); }
}

5

मेरी सिफारिश http://systemwrapper.codeplex.com/ का उपयोग करने के लिए है क्योंकि यह सिस्टम नामस्थान में अधिकतर उपयोग किए जाने वाले प्रकारों के लिए आवरण प्रदान करता है


मैं वर्तमान में इस लाइब्रेरी का उपयोग कर रहा हूं, और अब जब मुझे पता चला है कि फाइलस्ट्रीम जैसी चीजों के लिए इसके सार में आईडीसोफिल शामिल नहीं है, तो मैं एक प्रतिस्थापन की तलाश में हूं। यदि पुस्तकालय मुझे धाराओं के निपटान के लिए अनुमति नहीं देता है, तो मैं उन प्रकार के संचालन को संभालने के लिए इसकी अनुशंसा (या उपयोग) नहीं कर सकता।
जेम्स नेल

1
SystemWrapper की IFileStreamWrap अब IDisposable को लागू करती है।
tster

systemwrapper .net फ्रेमवर्क ही है, अगर यह .netcore के साथ प्रयोग किया जाता है तो अजीब मुद्दे पैदा करेगा
आदिल एच। रज़ा

3

मैं निम्नलिखित समाधानों के पार आया हूँ:

  • एकीकरण परीक्षण लिखें, इकाई परीक्षण नहीं। यह काम करने के लिए आपको एक फ़ोल्डर बनाने का एक सरल तरीका चाहिए जहां आप अन्य परीक्षणों के हस्तक्षेप के बारे में चिंता किए बिना सामान डंप कर सकते हैं। मेरे पास एक सरल TestFolder वर्ग है जो उपयोग करने के लिए एक अद्वितीय प्रति परीक्षण विधि फ़ोल्डर बना सकता है।
  • एक मजाकिया System.IO.File लिखें। यह एक IFile.cs बना है । मुझे पता है कि यह अक्सर परीक्षणों के साथ समाप्त होता है जो साबित करते हैं कि आप मजाकिया बयान लिख सकते हैं, लेकिन इसका उपयोग तब करें जब आईओ का उपयोग छोटा हो।
  • आप अमूर्त की परत का परीक्षण करें, और कक्षा से फ़ाइल IO निकालें। इसके लिए एक इंटरफ़ेस बनाएँ। शेष उपयोग एकीकरण परीक्षण (लेकिन यह बहुत छोटा होगा)। यह फ़ाइल करने के बजाय ऊपर से अलग है। क्या आप इरादे लिखते हैं, ioThingie.loadSettings ()
  • सिस्टम । मैंने अभी तक इसका उपयोग नहीं किया है, लेकिन यह वह है जिसके साथ खेलने के लिए मैं सबसे अधिक उत्साहित हूं।

मैं उपरोक्त सभी विधियों का उपयोग कर रहा हूं, जो मैं लिख रहा हूं, उसके आधार पर। लेकिन जब मैं इकाई परीक्षण लिखता हूं, तो अधिकांश समय मैं सोचता हूं कि अमूर्तता गलत है।


4
IFile.cs से लिंक टूट गया है।
माइक-ई

3

System.IO.Abstractions और System.IO.Abstractions.TestingHelpers का उपयोग करके :

public class ManageFile {
   private readonly IFileSystem _fileSystem;
   public ManageFile(IFileSystem fileSystem){

      _fileSystem = fileSystem;
   }

   public bool FileExists(string filePath){}
       if(_fileSystem.File.Exists(filePath){
          return true;
       }
       return false;
   }
}

अपने टेस्ट क्लास में, आप MockFileSystem () का उपयोग मॉक फाइल करने के लिए करते हैं और आप ManageFile को इंस्टेंट करते हैं:

var mockFileSysteme = new MockFileSystem();
var mockFileData = new MockFileData("File content");
mockFileSysteme.AddFile(mockFilePath, mockFileData );
var manageFile = new ManageFile(mockFileSysteme);

2

आप यह कर सकते हैं कि उदाहरण के लिए अपने कोडबेस को बदलने की आवश्यकता के बिना Microsoft फ़ेक का उपयोग करना क्योंकि यह पहले से ही जमे हुए था।

पहले System.dll - या किसी अन्य पैकेज के लिए एक नकली असेंबली बनाएँ और फिर निम्न के रूप में अपेक्षित रिटर्न का मज़ाक उड़ाएँ:

using Microsoft.QualityTools.Testing.Fakes;
...
using (ShimsContext.Create())
{
     System.IO.Fakes.ShimFile.ExistsString = (p) => true;
     System.IO.Fakes.ShimFile.ReadAllTextString = (p) => "your file content";

      //Your methods to test
}

1

एक परीक्षण में फाइल सिस्टम का मजाक उड़ाना मुश्किल होगा क्योंकि .NET फाइल एपीआई वास्तव में इंटरफेस या एक्स्टेंसिबल क्लास पर आधारित नहीं होते हैं, जिनका मजाक उड़ाया जा सकता है।

हालाँकि, यदि आपके पास फ़ाइल सिस्टम तक पहुँचने के लिए अपनी स्वयं की कार्यात्मक परत है, तो आप इसे एक इकाई परीक्षण में नकली कर सकते हैं।

मॉकिंग के विकल्प के रूप में, अपने परीक्षण सेटअप के भाग के रूप में आपके द्वारा आवश्यक फ़ोल्डर और फ़ाइलें बनाने पर विचार करें, और उन्हें अपने अश्रु विधि में हटा दें।


1

मुझे यकीन नहीं है कि आप फाइल सिस्टम का मजाक कैसे उड़ाएंगे। आप जो कर सकते थे, वह एक परीक्षण स्थिरता सेटअप है जो परीक्षण के लिए आवश्यक संरचना के साथ एक फ़ोल्डर आदि बनाता है। परीक्षणों के चलने के बाद एक फाड़नेवाला विधि इसे साफ कर देती है।

जोड़ने के लिए संपादित: इस बारे में थोड़ा और सोचने पर, मुझे नहीं लगता कि आप इस प्रकार के तरीकों का परीक्षण करने के लिए फाइल सिस्टम का मजाक बनाना चाहते हैं। यदि आप किसी निश्चित फ़ाइल के मौजूद होने पर फ़ाइल सिस्टम को सही होने के लिए मॉक करते हैं और उस पद्धति के अपने परीक्षण में इसका उपयोग करते हैं जो यह जाँचता है कि क्या फ़ाइल मौजूद है, तो आप किसी भी चीज़ का अधिक परीक्षण नहीं कर रहे हैं। जहाँ फ़ाइल सिस्टम का मज़ाक उड़ाना उपयोगी होगा, अगर आप किसी ऐसे तरीके का परीक्षण करना चाहते हैं, जिसकी फ़ाइल सिस्टम पर निर्भरता हो, लेकिन परीक्षण के तहत फ़ाइल सिस्टम गतिविधि विधि के साथ अभिन्न नहीं थी।


1

आपके विशिष्ट प्रश्न का उत्तर देने के लिए: नहीं, ऐसी कोई लाइब्रेरी नहीं है जो आपको I / O कॉल (जो मुझे पता है) की फाइल को मॉक करने देगी। इसका मतलब यह है कि आपके प्रकारों का परीक्षण करने वाली "उचित" इकाई के लिए आवश्यक होगा कि आप इस प्रतिबंध को तब ध्यान में रखें जब आप अपने प्रकारों को परिभाषित करते हैं।

त्वरित पक्ष ध्यान दें कि मैं "उचित" इकाई परीक्षण को कैसे परिभाषित करता हूं। मेरा मानना ​​है कि यूनिट परीक्षणों से यह पुष्टि होनी चाहिए कि आपको अपेक्षित आउटपुट मिले (एक अपवाद, किसी विधि पर कॉल आदि) ज्ञात इनपुट प्रदान किए जाएं। यह आपको इनपुट और / या इनपुट राज्यों के एक सेट के रूप में अपनी इकाई परीक्षण स्थितियों को सेट करने की अनुमति देता है। सबसे अच्छा तरीका है कि मैं ऐसा करने के लिए इंटरफ़ेस-आधारित सेवाओं और निर्भरता इंजेक्शन का उपयोग कर रहा हूं ताकि एक प्रकार के लिए बाहरी प्रत्येक जिम्मेदारी एक निर्माता या संपत्ति के माध्यम से पारित इंटरफ़ेस के माध्यम से प्रदान की जाए।

तो, इसे ध्यान में रखते हुए, अपने प्रश्न पर वापस जाएं। मैंने IFileSystemServiceएक FileSystemServiceकार्यान्वयन के साथ एक इंटरफ़ेस बनाकर फाइल सिस्टम कॉल का मजाक उड़ाया है जो कि mscorlib फाइल सिस्टम के तरीकों का एक पहलू है। मेरा कोड तब IFileSystemServicemscorlib प्रकारों के बजाय उपयोग करता है । यह मुझे अपने मानक में प्लग करने की अनुमति देता है FileSystemServiceजब एप्लिकेशन चल रहा होता है या IFileSystemServiceमेरी इकाई परीक्षणों में मॉक होता है । एप्लिकेशन कोड समान है कि यह कैसे चलाया जाता है, लेकिन अंतर्निहित आधारभूत संरचना उस कोड को आसानी से जांचने की अनुमति देती है।

मैं स्वीकार करता हूं कि यह mscorlib फ़ाइल सिस्टम ऑब्जेक्ट्स के आसपास रैपर का उपयोग करने के लिए एक दर्द है, लेकिन इन विशिष्ट परिदृश्यों में, यह अतिरिक्त काम के लायक है क्योंकि परीक्षण इतना आसान और अधिक विश्वसनीय हो जाता है।


1

एक इंटरफ़ेस बनाना और परीक्षण के लिए इसका मज़ाक उड़ाना सबसे अच्छा तरीका है। हालाँकि, एक वैकल्पिक यो के रूप में Microsoft मोल्स फ्रेमवर्क पर एक नज़र डाल सकता है।


0

सामान्य समाधान कुछ अमूर्त फाइलसिस्टम एपीआई (जैसे जावा के लिए अपाचे कॉमन्स वीएफएस ) का उपयोग कर रहा है: सभी एप्लिकेशन लॉजिक एपीआई का उपयोग करता है और यूनिट टेस्ट स्टब कार्यान्वयन (इन-मेमोरी एमुलेशन या ऐसा कुछ) के साथ वास्तविक फाइलसिस्टम को मॉक करने में सक्षम है।

C # के लिए समान API मौजूद है: NI.Vfs जो अपाचे VFS V1 के समान है। इसमें स्थानीय फाइल सिस्टम और इन-मेमरी फाइलसिस्टम (पिछले एक को बॉक्स से यूनिट टेस्ट में इस्तेमाल किया जा सकता है) के लिए डिफ़ॉल्ट कार्यान्वयन शामिल हैं।


-1

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


-2

मैं जेमी इडे की प्रतिक्रिया के साथ जाऊंगा। जो चीजें आपने नहीं लिखीं, उनका मजाक उड़ाने की कोशिश न करें। निर्भरता के सभी तरीके होंगे जिनके बारे में आप नहीं जानते थे - सील की गई कक्षाएं, गैर आभासी तरीके आदि।

एक और तरीका यह होगा कि किसी चीज के साथ विनोदी तरीकों को लपेटें जो कि नकली हो। उदा। FileWrapper नामक एक वर्ग बनाएँ जो फ़ाइल विधियों तक पहुँच की अनुमति देता है लेकिन कुछ ऐसा है जिसे आप मॉक आउट कर सकते हैं।

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