2014-05-04 7 views
15

मैं डीबीकॉन्टेक्स्ट और डीबीसेट को नकल करने की कोशिश कर रहा हूं। यह मेरे पिछले यूनिट परीक्षणों के लिए काम करता है, लेकिन समस्या तब होती है जब मेरा कोड डीबीसेट पर दूसरी बार ToList विधि को कॉल कर रहा था।डीबीसेट मैक, टूलीस्ट को दूसरी बार कॉल करने के दौरान कोई परिणाम नहीं

पहला डीबीसेट। टोलिस्ट() मजाकिया परिणाम देता है। दूसरा एक 0 तत्व देता है;

 var queryableData = new List<string>{ "a", "b", "c" }.AsQueryable(); 

     var mockDbSet = new Mock<DbSet<string>>(); 
     var q = mockDbSet.As<IQueryable<string>>(); 
     q.Setup(m => m.Provider).Returns(queryableData.Provider); 
     q.Setup(m => m.Expression).Returns(queryableData.Expression); 
     q.Setup(m => m.ElementType).Returns(queryableData.ElementType); 
     q.Setup(m => m.GetEnumerator()).Returns(queryableData.GetEnumerator()); 

     DbSet<string> dbset = mockDbSet.Object; 
     IQueryable<string> query = dbset; 

     //RESULTS: abc 
     var a1 = dbset.ToList(); 
     foreach (var a in a1) 
      Console.Write(a); 

     //NO RESULTS 
     var a2 = dbset.ToList(); 
     foreach (var a in a2) 
      Console.Write(a); 

उत्तर

36

आप GetEnumerator की प्रत्येक कॉल पर बहुत ही प्रगणक उदाहरण लौट आते हैं। जब यह एक बार गणना करता है, यह किया जाता है, ईएफ अपनी Reset विधि को कॉल नहीं करता है, बल्कि यह एक नया गणक मांगता है।

लेकिन आप उस व्यक्ति को वापस लौटते हैं जिसने सभी तत्वों को पैदा किया है और अब और उपज नहीं है।

इसके बजाय, एक फ़ंक्शन लौटाएं जो गणनाकर्ता को लौटाता है, जो हर बार जब आप इसके लिए पूछते हैं तो एक नया गणक वापस कर देगा।

q.Setup(m => m.GetEnumerator()).Returns(() => queryableData.GetEnumerator()); 
+0

यह मुझे मार रहा था। ग्रेट कैच – RMD

+0

यह मेरे लिए कुछ महीनों के लिए एक भालू रहा है। मैं अंत में एक ऐसी स्थिति में आया जहां मैं इससे बच नहीं पाया। इससे बहुत मदद मिली! –

+0

इसने मेरे जीवन को इतना बेहतर बना दिया। धन्यवाद। –

0

यदि आप पहले .ToList() कॉल एक "कहाँ" खंड में कहें, डेटा उपस्थित रहना चाहिए।

var a1 = dbset.Where(m => m != null).ToList(); 

var a2 = dbset.Where(m => m != null).ToList(); 
2

मैं सिर्फ विक्टर ज़िचला के जवाब को अपने छोटे हिस्से में जोड़ना चाहता था। किसी को इस नकली की Async संस्करण की तलाश में है तो (इस ट्यूटोरियल से आ रही: http://msdn.microsoft.com/en-us/data/dn314429.aspx#async):

internal class TestDbAsyncEnumerator<T> : IDbAsyncEnumerator<T> 
{ 
    private readonly IEnumerator<T> _inner; 

    public TestDbAsyncEnumerator(IEnumerator<T> inner) 
    { 
     _inner = inner; 
    } 

    public TestDbAsyncEnumerator(Func<IEnumerator<T>> valueFunction) 
    { 
     _inner = valueFunction(); 
    } 

    public void Dispose() 
    { 
     _inner.Dispose(); 
    } 

    public Task<bool> MoveNextAsync(CancellationToken cancellationToken) 
    { 
     return Task.FromResult(_inner.MoveNext()); 
    } 

    public T Current 
    { 
     get { return _inner.Current; } 
    } 

    object IDbAsyncEnumerator.Current 
    { 
     get { return Current; } 
    } 
} 

तब विक्टर तरह का सुझाव दिया है आप async के मामले में प्रतिनिधि के साथ सेटअप करने के लिए है, तो फिर इस TestDbAsyncEnumerator<T> वर्ग के लिए मेरी संशोधन है यह ऐसा होगा:

mockSet.As<IDbAsyncEnumerable<Blog>>() 
      .Setup(m => m.GetAsyncEnumerator()) 
      .Returns(new TestDbAsyncEnumerator<Blog>(() => data.GetEnumerator())); 

किसी को उस के लिए स्रोत चाहता है तो ये रहा: https://github.com/kelostrada/EntityFrameworkWithMock.Test

+0

आपके गिटहब रेपो में कोड स्टैक ओवरफ्लो में आपके पास मेल नहीं खाता है? मेरे मामले में किसी भी तरह से काम नहीं करता है। – Riga

+0

आपके लिए क्या काम नहीं कर रहा है?मैंने इस कोड को 2 से अधिक वर्षों तक नहीं देखा है, यह कुछ पैकेज अपडेट और उस तरह की चीजों के कारण काम नहीं कर सकता है। क्या यह संकलित नहीं है? इसके अलावा मुझे पता चला कि डीबीसेट्स का नकल करने की कोशिश करना सबसे कठिन काम था जैसा मैंने कभी संपर्क किया था ... कभी भी कोशिश नहीं करेगा। बस परीक्षण के लिए एक नया डेटाबेस स्थापित करें और प्रत्येक परीक्षण पर एक लेनदेन सेट करें - अधिक विश्वसनीय और उपयोग करने में आसान समाधान। (शायद केवल थोड़ी धीमी) –

+0

मेरी टिप्पणी यहां कोड के बारे में अधिक है और आपके द्वारा लिंक किए गए भंडार में मेल नहीं खाता है। आपका कोड बनाता है, लेकिन यहां वर्णित समान समस्या को ठीक नहीं करता है: http://stackoverflow.com/questions/41899177/mock-entity-framework-long-linq-query/41900708#41900708। अब समझें कि डबसेट्स को मजाक करना बहुत कठिन तरीका है और शायद सबसे अच्छा नहीं, सोचा कि ईएफ टेस्टेबल होने के लिए बनाया गया था, लेकिन शायद नहीं। काम करने वाली परियोजना में चीजों को बदलने के लिए बहुत देर हो चुकी है। धन्यवाद। – Riga

2

मैं विक्टर की पोस्ट पर टिप्पणी नहीं कर सकते हैं के रूप में मैं काफी प्रतिष्ठा नहीं मिला है, लेकिन मैं होगा विकटोर के जवाब में थोड़ा अतिरिक्त जोड़ना पसंद है।

कोड

mockSet.Setup((m => m.GetEnumerator()).Returns(() => data.GetEnumerator()) 

यदि आप इसे एक शून्य तर्क लैम्ब्डा की तरह उदाहरण में (कम से कम संस्करण मैं उपयोग कर रहा हूँ) देना असफल हो जायेगी। कभी भी उपयोग किए जाने वाले तर्क को पास करने से यह हस्ताक्षर आवश्यकता को पूरा करने की अनुमति नहीं देगा।

mockSet.Setup((m => m.GetEnumerator()).Returns(x => data.GetEnumerator()) 

हालांकि संकलित करेगा, और अपेक्षा के अनुसार काम करेगा।

और यह भी रूप में अच्छी तरह हालांकि वह गलत जगह पर लैम्ब्डा जोड़ा गया है Kelu के जवाब देने के लिए लागू होता है (।

mockSet.As<IDbAsyncEnumerable<Blog>>() 
     .Setup(m => m.GetAsyncEnumerator()) 
     .Returns(x => new TestDbAsyncEnumerator<Blog>(data.GetEnumerator())); 

यहाँ जवाब nitpick करने के लिए, मैं सिर्फ इसलिए कि मैं अपने आप इन गलतियाँ की जोड़ रहा कोशिश कर नहीं :)

संबंधित मुद्दे