2012-10-13 21 views
25

के साथ विभिन्न पैरामीटर के लिए दो बार विधि को कैसे सेट अप करें, मैं दो बार Moq के साथ एक विधि सेट अप करना चाहता हूं लेकिन ऐसा लगता है कि अंतिम व्यक्ति पिछले लोगों को ओवरराइड करता है। यहाँ मेरी प्रारंभिक सेटअप है:नकली

string username = "foo"; 
string password = "bar"; 

var principal = new GenericPrincipal(
    new GenericIdentity(username), 
    new[] { "Admin" }); 

var membershipServiceMock = new Mock<IMembershipService>(); 
membershipServiceMock.Setup(ms => 
    ms.ValidateUser(username, password) 
).Returns(new ValidUserContext { 
    Principal = principal 
}); 

यह ठीक से काम करता है, लेकिन मैं इस new ValidUserContext() वापस जाने के लिए है, तो उपयोगकर्ता नाम या पासवर्ड से ऊपर के रूप में username और password चर के बजाय है चाहता हूँ। ऐसा करने के लिए, मैं एक और सेटअप जोड़ा है, लेकिन इस बार यह ऊपर एक ओवरराइड करता है और हमेशा यह लागू होता है:

membershipServiceMock.Setup(ms => 
    ms.ValidateUser(It.IsAny<string>(), It.IsAny<string>()) 
).Returns(
    new ValidUserContext() 
); 

Moq के साथ स्थितियों के इस प्रकार से निपटने में सबसे खूबसूरत तरीका क्या है?

संपादित

मैं नीचे दृष्टिकोण के साथ समस्या हल हो लेकिन मुझे लगता है कि वहाँ इस से निपटने का एक बेहतर तरीका है:

var membershipServiceMock = new Mock<IMembershipService>(); 
membershipServiceMock.Setup(ms => 
    ms.ValidateUser(It.IsAny<string>(), It.IsAny<string>()) 
).Returns<string, string>((u, p) => 
    (u == username && p == password) ? 
    new ValidUserContext { 
     Principal = principal 
    } 
    : new ValidUserContext() 
); 

उत्तर

35

Moq तर्क बाधाओं के साथ बॉक्स से बाहर इस का समर्थन करता है:

mock.Setup(ms => ms.ValidateUser(
     It.Is<string>(u => u == username), It.Is<string>(p => p == password)) 
    .Returns(new ValidUserContext { Principal = principal }); 
mock.Setup(ms => ms.ValidateUser(
     It.Is<string>(u => u != username), It.Is<string>(p => p != password)) 
    .Returns(new ValidUserContext()); 

कैच-ऑलIt.IsAny भी काम करता है, लेकिन क्रम महत्वपूर्ण है:

// general constraint first so that it doesn't overwrite more specific ones 
mock.Setup(ms => ms.ValidateUser(
     It.IsAny<string>(), It.IsAny<string>()) 
    .Returns(new ValidUserContext()); 
mock.Setup(ms => ms.ValidateUser(
     It.Is<string>(u => u == username), It.Is<string>(p => p == password)) 
    .Returns(new ValidUserContext { Principal = principal }); 
+1

पहला समाधान केस को संभाल नहीं करता है जब आप == उपयोगकर्ता नाम और पी! = पासवर्ड, या करता है? –

2

एक और बॉक्स विकल्प से बाहर मापदंडों के आधार पर अलग अलग ValidUserContexts लौटने के लिए वापसी <> संस्करण का उपयोग करने के लिए है। यह उपर्युक्त उत्तर से बेहतर नहीं है, बस एक और विकल्प है।

हम उपयोगकर्ता नाम और पासवर्ड में गुजरने वाले फ़ंक्शन GetUserContext (स्ट्रिंग, स्ट्रिंग) के परिणाम को वापस करने के लिए ValidateUser() सेटअप करते हैं जिसके साथ ValidateUser() को कॉल किया गया था।

[TestClass] 
public class MultipleReturnValues { 

    public class ValidUserContext { 
     public string Principal { get; set; } 
    } 

    public interface IMembershipService { 
     ValidUserContext ValidateUser(string name, string password); 
    } 

    [TestMethod] 
    public void DifferentPricipals() { 

     var mock = new Mock<IMembershipService>(); 
     mock.Setup(mk => mk.ValidateUser(It.IsAny<string>(), It.IsAny<string>())).Returns<string, string>(GetUserContext); 

     var validUserContext = mock.Object.ValidateUser("abc", "cde"); 

     Assert.IsNull(validUserContext.Principal); 


     validUserContext = mock.Object.ValidateUser("foo", "bar"); 

     Assert.AreEqual(sPrincipal, validUserContext.Principal); 


    } 

    private static string sPrincipal = "A Principal"; 
    private static ValidUserContext GetUserContext(string name, string password) { 

     var ret = new ValidUserContext(); 

     if (name == "foo" && password == "bar") { 
      ret = new ValidUserContext { Principal = sPrincipal }; 
     } 
     return ret; 

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