How to unit test [requiresauthentication] domainservice
In the previous articleArticleHow to perform unit testing in Silverlight, if your client SilverlightCodeIt calls the domainservice marked with [requiresauthentication] In the WCF Ria service, so you will have trouble in unit testing the code, because an error will be reported when calling these domainservices and authentication is required. (For details about enalbe authentication in WCF Ria service, refer to this msdn page)
This problem occurs when you test any class that calls [requiresauthentication] domainservice, such as viewmodel.
Some people say that you want to test the domainservice with [requiresauthentication? You can use the basic method to test the domainservice logic. It is not necessary to test [requiresauthentication. Yes, yes, but can you test the Silverlight viewmodel? In viewmodel, you call the domainservice method of [requiresauthentication]. Will this happen to you? If the answer is yes, you cannot solve this problem.
For example, the Silverlight application is developed in mvvm mode, and we separate the parts about domaincontext calling the WCF Ria service from the viewmodel to the service. In this way, our service will use domaincontext to call the WCF Ria service. If the RIA service enables authentication, that is, the domainservice marked with [requiresauthentication] In the WCF Ria service, then we will fail to test the service, because authenciation is required. Similarly, if you directly place the logic in the viewmodel without the service layer, your viewmodel cannot be tested. Unless you bypass this issue and use a mock object, however, the WCF Ria service is asynchronous and there is a problem with the authenticity of the simulation. In short, we need to solve the authentication problem, rather than attempting to bypass the problem.
Exception: load operation failed for query 'getproducts'. Access to Operation 'getproducts' was denied.
Message: system. servicemodel. domainservices. Client. domainoperationexception:
Load Operation failed for query 'getproducts'. Access to Operation 'getproducts' was denied.
At system. servicemodel. domainservices. Client. operationbase. Complete (Exception error)
At system. servicemodel. domainservices. Client. loadoperation. Complete (Exception error)
At system. servicemodel. domainservices. Client. domaincontext. completeload (iasyncresult asyncresult)
At system. servicemodel. domainservices. Client. domaincontext. <> C _ displayclass1b. <load> B _ 17 (object)
When your code calls the [requireauthentication] domainservice of the WCF Ria service, this error will be reported during the test.
Example of domainservice marked with [requiresauthentication]
1:[Enableclientaccess ()]
2:[Requiresauthentication()]
3:Public ClassAdventureworksdomainservice: linqtoentitiesdomainservice <adventureworkslt_dataentities>
4:{
5:[Requiresrole("Managers")]
6: PublicIqueryable <customer> getcustomers ()
7:{
8: Return This. Objectcontext. customers;
9:}
10:
11: PublicIqueryable <product> getproducts ()
12:{
13: Return This. Objectcontext. Products;
14:}
15:
16: PublicIqueryable <salesorderheader> getsalesorderheaders ()
17:{
18: Return This. Objectcontext. salesorderheaders;
19:}
20:}
Solution to requireauthentication
In fact, the idea is very clear, that is, testingProgramCall the user to log on and then run the test case!
Solution Step 1: Configure app. XAML to delete lifetimeobjects
Delete the following content of APP. xaml of the test project:
1:<Application. applicationlifetimeobjects>
2: <APP: webcontext>
3: <APP: webcontext. Authentication>
4: <Required VC: formsauthentication />
5: </APP: webcontext. Authentication>
6: </APP: webcontext>
7:</Application. applicationlifetimeobjects>
Solution Step 2: add the partial webcontext class
Add a class in APP. XAML. CS of the test project.
1 Public Partial Class Webcontext: webcontextbase
2 {
3 Partial Void Oncreated ();
4 Public Webcontext ()
5 {
6 This . Oncreated ();
7 }
8 Public New Static Webcontext current
9 {
10 Get
11 {
12 Return (Webcontext) (webcontextbase. Current ));
13 }
14 }
15 Public New User user
16 {
17 Get
18 {
19 Return (User )( Base . User ));
20 }
21 }
22 }
Solution Step 3: manually create applicationlifetimeobjects 1 Public APP ()
2 {
3 This . Startup + = This . Application_startup;
4 This . Exit + = This . Application_exit;
5 This . Unhandledexception + = This . Application_unhandledexception;
6
7 Initializecomponent ();
8
9 // Add the following code :************************************
10 Webcontext = New Webcontext (); // This is the webcontext we just created.
11 Webcontext. Authentication = New System. servicemodel. domainservices. Client. applicationservices. formsauthentication ();
12 This . Applicationlifetimeobjects. Add (webcontext );
13 }
Solution Step 4: automatically authentication upon startup of the Test Program
Add the following code to app. XAML. CS of the test project:
1 Private Authenticationdomaincontext authctx;
2
3 Private Void Application_startup ( Object Sender, startupeventargs E)
4 {
5 Authctx = New Authenticationdomaincontext ();
6
7 Webcontext. Current. Authentication = New Formsauthentication
8 {
9 Domaincontext = New Authenticationdomaincontext ()
10 };
11
12 Authenticationservice auth = Webcontext. Current. authentication; // The created webcontext
13 If ( ! Auth. isloggingin)
14 {
15 Auth. login ( New Loginparameters ( " Yourusername " , " Yourpassword " , False , Null ), Logincompleted, Null );
16 }
17
18 // The test page is displayed after logon is complete.
19 // Rootvisual = unittestsystem. createtestpage ();
20 }
21
22 Private Void Logincompleted (loginoperation)
23 {
24 If (Loginoperation. loginsuccess)
25 {
26 // Login successful display test page
27 Rootvisual = Unittestsystem. createtestpage ();
28 }
29 }
Summary
the entire process is very simple, so that we can easily test any domain service class and method to be authenticated. ( note : if you do not understand Silverlight unit testing, WCF Ria service, domainservice, Ria authentication, webcontext, mvvm mode, and so on, read this article, you can read my other articles in this series first .)