2012-02-05 34 views
8

का उपयोग करते समय ASP.NET MVC 3 प्रमाणीकरण का परीक्षण कैसे करें मैं अपने AccountController का परीक्षण करना चाहता हूं।सदस्यता

Membership.CreateUser(model.Email, model.Password, model.Email, null, null, true, null, out createStatus); 

वेब अनुप्रयोग में मैं एक CustomMembershipProvider जो मैं web.config का उपयोग कर सेट का उपयोग करें: समस्या यह है कि रजिस्टर विधि में मैं उपयोगकर्ता बनाने के लिए अगली पंक्ति का उपयोग करें। मानक यूनिट परीक्षण सदस्यता वर्ग में मानक SqlMembershipProvider में। और मेरे CustomMembershipProvider नहीं कि मैं अपने ऐप में उपयोग करता हूं।

मैं इकाई परीक्षण संदर्भ में सदस्यता कैसे स्थापित कर सकता हूं? मेरा मतलब यह है कि इसे web.config फ़ाइल पढ़ने के बाद इसे एएसपी नेट सेट के रूप में प्रोग्रामेटिक रूप से सेट करना है।

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

public void RegisterTest() 
{ 
    IUsersManager repository = new Tests.Data.UsersManager(); 
    AccountController target = new AccountController(repository); 
    //be able to set Membership underlying provider 
    Membership.Provider = new MockMembershipProvider(); 
} 

उत्तर

8

एक सदस्यता इंटरफेस को परिभाषित करें, कुछ इस तरह:

public interface IMembershipProvider 
{ 
    void CreateUser(string username, string password); 
} 

... इस तरह अपने MVC आवेदन के लिए इसे लागू:

public class AspDotNetMembershipProvider : IMembershipProvider 
{ 
    public void CreateUser(string username, string password) 
    { 
     string createStatus; 

     Membership.CreateUser(
      username, 
      password, 
      username, 
      null, 
      null, 
      true, 
      null, 
      out createStatus); 

     // throw an exception if createStatus isn't as expected 
    } 
} 

... तो को इसकी सुई अपने नियंत्रक और इसका उपयोग इस प्रकार करें:

public class AccountController 
{ 
    private readonly IMembershipProvider _membershipProvider; 

    public AccountController(IMembershipProvider membershipProvider) 
    { 
     this._membershipProvider = membershipProvider; 
    } 

    public ActionResult Register(RegistrationModel model) 
    { 
     // Try and catch this, returning a success ActionResult if it worked: 
     this._membershipProvider.CreateUser(model.Email, model.Password); 
    } 
} 

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

आप डिफ़ॉल्ट DependencyResolver और Unity जैसे डी कंटेनर का उपयोग कर इंजेक्शन (यदि आपने पहले से नहीं किया है) सेट अप कर सकते हैं।

+1

'AspDotNetMembershipProvider' इंटरफ़ेस को लागू नहीं करना चाहिए? 'पब्लिक क्लास AspDotNetMembershipProvider की तरह: IMembershipProvider {... ' – marapet

+0

ओह, निश्चित रूप से यह होना चाहिए। ठीक किया गया, धन्यवाद :) –

+0

'सदस्यता' वर्ग स्थिर है ... लेकिन अंतर्निहित प्रदाता एएसपी रनटाइम द्वारा सेट किया गया है ... और मैं सोच रहा था कि मैं इसे –

0

नियंत्रक के आपके यूनिट परीक्षण को आपके CustomMembershipProvider या मानक SQL प्रदाता का उपयोग नहीं करना चाहिए। यदि यूनिट टेस्ट कर रहे हैं तो आपको स्टब/नकली का उपयोग करना चाहिए कि आपके पास वापस लौटने पर पूरा नियंत्रण है। यदि आप परीक्षण में वास्तविक प्रदाता का उपयोग कर रहे हैं तो यह अब यूनिट परीक्षण नहीं है, यह एकीकरण परीक्षण है।

यूनिट टेस्टेबिलिटी प्राप्त करने के लिए आपको नकली प्रदाता को परिभाषित करने की आवश्यकता है, या तो मॉकिंग फ्रेमवर्क का उपयोग करके या "डिब्बाबंद" परिणामों के साथ नकली रोलिंग हाथ से। नकली कुछ इस तरह दिखाई दे सकता है:

public class FakeMembershipProvider : MembershipProvider 
{ 
    public MembershipCreateStatus CreateStatus = MembershipCreateStatus.Success; 

    public void CreateUser((string username, string password, string email, 
     string passwordQuestion, string passwordAnswer, bool isApproved, 
     object providerUserKey, out MembershipCreateStatus status) 
    { 
     status = CreateStatus; 
    } 

    ... 
} 

नियंत्रक एक ctor तर्क

public class AccountController 
{ 
    private readonly MembershipProvider _membershipProvider; 

    public AccountController(MembershipProvider membershipProvider) 
    { 
     _membershipProvider = membershipProvider; 
    } 

    public ActionResult Register(RegistrationModel model) 
    { 
     MembershipCreateStatus result; 
     _membershipProvider.CreateUser(model.Email, model.Password, ..., out result); 

     return View(/*Make this depend on the result*/); 
    } 
} 

यूनिट परीक्षण में के रूप में प्रदाता लेते हैं कि तुम क्या आप परीक्षण करना चाहते करने के लिए और अनुसार नकली सेटअप करना चाहते हैं आप परिणाम है कि आप प्रत्येक पंजीकरण परिणाम के लिए उम्मीद का दावा कर सकते हैं:

[Test] 
void Should_display_success_view_when_user_successfully_created() 
{ 
    var membershipProvider = new FakeMembershipProvider(); 
    membershipProvider.CreateStatus = MembershipCreateStatus.Success; 
    var controller = new AccountController(membershipProvider); 
    var model = new RegistrationModel(); 

    var result = controller.Register(model) as ViewResult; 

    Assert.That(result.Name, Is.EqualTo("ExpectedViewName"));  
} 

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

2

मैंने एक और अधिक संरचित सदस्यता प्रदाता बनाया है जो तीन अलग-अलग इंटरफेस में टूट गया है (और प्रदाता DependencyResolver का उपयोग करके उन्हें हल कर रहा है)।

यह इकाई को प्रदाता का परीक्षण करना आसान बनाता है। बस IAccountRepository के अपने कार्यान्वयन का परीक्षण करें।

आप इसके बारे में यहाँ पढ़ सकते हैं: http://blog.gauffin.org/2011/09/a-more-structured-membershipprovider/

या सिर्फ nuget पैकेज स्थापित:

install-package griffin.mvccontrib 
संबंधित मुद्दे