2011-07-11 12 views
13

मैं के साथ, अन्य लोगों के अलावा, निम्न विधि कार्य कार्यान्वयन का एक यूनिट है:लैम्ब्डा अभिव्यक्ति के साथ विधि कॉल सत्यापित करें - Moq

T Single<T>(Expression<Func<T, bool>> expression) where T : class, new(); 

और मैं इसे कहते हैं, उदाहरण के लिए, इस तरह:

var person = _uow.Single<Person>(p => p.FirstName == "Sergi"); 

मैं कैसे सत्यापित कर सकता हूं कि Single विधि FirstName == "Sergi" के तर्क के साथ बुलाया गया है?

मैं निम्नलिखित की कोशिश की है, लेकिन कोई लाभ नहीं हुआ:

// direct approach 
session.Verify(x => x.Single<Person>(p => p.FirstName == "Sergi")); 

// comparing expressions 
Expression<Func<Person, bool>> expression = p => p.FirstName == "Sergi"); 

session.Verify(x => x 
    .Single(It.Is<Expression<Func<Person, bool>>>(e => e == expression)); 

वे folowing त्रुटि में सभी परिणाम:

Expected invocation on the mock at least once, but was never performed

पर कैसे कोई भी विचार किया जा सकता है? मैं NuGet से नवीनतम Moq उपयोग कर रहा हूँ, संस्करण 4.0.10827.0

अद्यतन: एक विशिष्ट उदाहरण

क्या मैं दिखाई दे रही है है कि जब भी मैं लैम्ब्डा, Verify काम करता है अंदर स्ट्रिंग शाब्दिक का उपयोग करें। जैसे ही मैं चर की तुलना कर रहा हूं, यह विफल हो जाता है। बिंदु में मामला:

// the verify 
someService.GetFromType(QuestionnaireType.Objective) 

session.Verify(x => x.Single<Questionnaire>(q => 
    q.Type == QuestionnaireType.Objective)); 


// QuestionnaireType.Objective is just a constant: 
const string Objective = "objective"; 


// the method where it's called (FAILS): 
public Questionnaire GetFromType(string type) 
{ 
    // this will fail the Verify 
    var questionnaire = _session 
     .Single<Questionnaire>(q => q.Type == type); 
} 

// the method where it's called (PASSES): 
public Questionnaire GetFromType(string type) 
{ 
    // this will pass the Verify 
    var questionnaire = _session 
     .Single<Questionnaire>(q => q.Type == QuestionnaireType.Objective); 
} 

कैसे आ Verify जैसे ही मैंने लैम्ब्डा अभिव्यक्ति में विधि पैरामीटर का उपयोग विफल रहता है?

इस परीक्षा को लिखने का सही तरीका क्या होगा?

उत्तर

11

सीधा रास्ता मेरे लिए ठीक काम करता है:

// direct approach 
session.Verify(x => x.Single<Person>(p => p.FirstName == "Sergi")); 

अभिव्यक्ति वस्तु बराबर भाव के लिए सच वापस नहीं करता है तो यह असफल हो जायेगी:

// comparing expressions 
Expression<Func<Person, bool>> expression = p => p.FirstName == "Sergi"); 

session.Verify(x => x 
    .Single(It.Is<Expression<Func<Person, bool>>>(e => e == expression)); 

को समझने के लिए क्यों, निम्नलिखित चलाने NUnit परीक्षण:

[Test] 
public void OperatorEqualEqualVerification() 
{ 
    Expression<Func<Person, bool>> expr1 = p => p.FirstName == "Sergi"; 
    Expression<Func<Person, bool>> expr2 = p => p.FirstName == "Sergi"; 
    Assert.IsTrue(expr1.ToString() == expr2.ToString()); 
    Assert.IsFalse(expr1.Equals(expr2)); 
    Assert.IsFalse(expr1 == expr2); 
    Assert.IsFalse(expr1.Body == expr2.Body); 
    Assert.IsFalse(expr1.Body.Equals(expr2.Body)); 
} 

और जैसा कि ऊपर दिया गया परीक्षण इंगित करता है, पूर्व की तुलना में अभिव्यक्ति शरीर भी असफल हो जायेगी, लेकिन स्ट्रिंग तुलना काम करता है, तो यह रूप में अच्छी तरह से काम करता है:

// even their string representations! 
session.Verify(x => x 
    .Single(It.Is<Expression<Func<Person, bool>>>(e => 
     e.ToString() == expression.ToString())); 

और यहाँ आप शस्त्रागार कि भी काम करता है को जोड़ सकते हैं परीक्षण का एक और शैली है:

[Test] 
public void CallbackVerification() 
{ 
    Expression<Func<Person, bool>> actualExpression = null; 
    var mockUow = new Mock<IUnitOfWork>(); 
    mockUow 
     .Setup(u => u.Single<Person>(It.IsAny<Expression<Func<Person, bool>>>())) 
     .Callback((Expression<Func<Person,bool>> x) => actualExpression = x); 
    var uow = mockUow.Object; 
    uow.Single<Person>(p => p.FirstName == "Sergi"); 

    Expression<Func<Person, bool>> expectedExpression = p => p.FirstName == "Sergi"; 

    Assert.AreEqual(expectedExpression.ToString(), actualExpression.ToString()); 
} 

आप के रूप में ऐसे कई परीक्षण मामले हैं जो असफल हो जाते हैं, आपको शायद एक अलग समस्या हो।

अद्यतन:

string normal_type = "NORMAL"; 
// PersonConstants is a static class with NORMAL_TYPE defined as follows: 
// public const string NORMAL_TYPE = "NORMAL"; 
Expression<Func<Person, bool>> expr1 = p => p.Type == normal_type; 
Expression<Func<Person, bool>> expr2 = p => p.Type == PersonConstants.NORMAL_TYPE; 

एक अभिव्यक्ति का संदर्भ युक्त विधि का एक उदाहरण चर: अगर आपके अपडेट के अनुसार, निम्न सेटअप और भाव पर विचार करें। दूसरा एक अभिव्यक्ति का प्रतिनिधित्व करता है जो स्थिर वर्ग के एक कॉन्स्ट सदस्य का संदर्भ देता है। रनटाइम पर चरों को आवंटित किए जा सकने वाले मानों के बावजूद, दोनों अलग-अलग अभिव्यक्तियां हैं।हालांकि, string normal_type को const string normal_type में बदल दिया गया है, तो अभिव्यक्ति अभिव्यक्ति के दाईं ओर const प्रत्येक संदर्भ के समान ही होती है।

+0

आपके उत्तर के लिए बहुत बहुत धन्यवाद। मैंने एक बेहतर शब्द की कमी के लिए नए एर ... निष्कर्षों के आधार पर अपना प्रश्न अपडेट कर लिया है। कोई विचार? –

+0

मैंने अपना प्रश्न यह अपडेट करने के लिए अपडेट किया है कि आपकी समस्या क्या हो सकती है। यह वास्तव में 'QuestionnaireType.Objective' के प्रकार पर निर्भर करता है। मैं उम्मीद करता हूं कि यदि आप दो अभिव्यक्तियों को 'ToString()' देखेंगे तो आप देखेंगे कि वे विभिन्न प्रकार के हैं। –

+0

फिर से धन्यवाद, मुझे लगता है कि यह समझ में आता है। लेकिन फिर इस परीक्षा को लिखने का सही तरीका क्या होगा? मुझे लगता है कि इस मामले में वाहन को स्पष्ट कोड के लिए मजाक करना और बाधा है ... –

1

मैं अपेक्षित अभिव्यक्ति में पैरामीटर अभिव्यक्ति की तुलना करने के लिए एक और दृष्टिकोण साझा करना भी चाहूंगा। मैं के लिए StackOverflow की खोज "कैसे भाव की तुलना करने," और मैं इन लेखों के लिए नेतृत्व किया गया था:

मैं तो db4o.net के लिए this Subversion repository करने के लिए नेतृत्व किया गया था। उनकी परियोजनाओं में से एक में, नामस्थान Db4objects.Db4o.Linq.Expressions, उनमें ExpressionEqualityComparer नामक कक्षा शामिल है। मैं इस परियोजना को अपने स्वयं के प्रोजेक्ट में उपयोग करने के लिए रिपोजिटरी, संकलन, निर्माण और डीएलएल बनाने के लिए चेकआउट करने में सक्षम था।

ExpressionEqualityComparer साथ

, तो आपको निम्न की तरह कुछ करने के लिए Verify कॉल संशोधित कर सकते हैं:

session.Verify(x => x .Single(It.Is<Expression<Func<Person, bool>>>(e => new ExpressionEqualityComparer().Equals(e, expression))));

अंत में, ExpressionEqualityComparer और ToString() तकनीक दोनों इस मामले में सच वापसी (ToString सबसे अधिक संभावना होने के साथ तेज - गति परीक्षण नहीं किया गया)। व्यक्तिगत रूप से, मैं तुलनात्मक दृष्टिकोण पसंद करता हूं क्योंकि मुझे लगता है कि यह अधिक आत्म-दस्तावेज है और आपके डिजाइन के इरादे को बेहतर ढंग से प्रतिबिंबित करता है (अभिव्यक्ति वस्तुओं की तुलना उनके टूस्ट्रिंग आउटपुट की स्ट्रिंग तुलना की तुलना में)।

नोट: मैं अभी भी इस परियोजना में एक db4o.net लाइसेंस फ़ाइल की तलाश में हूं, लेकिन मैंने कोड को संशोधित नहीं किया है, कॉपीराइट नोटिस शामिल है, और (चूंकि पृष्ठ सार्वजनिक रूप से उपलब्ध है) I मुझे लगता है कि अब के लिए पर्याप्त है ... ;-)

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