现在的位置: 首页 > 综合 > 正文

[Silverlight入门系列]如何单元测试RequiresAuthentication的DomainService

2011年01月20日 ⁄ 综合 ⁄ 共 5747字 ⁄ 字号 评论关闭

How to unit test [RequiresAuthentication] DomainService

我在上一篇文章中说了怎么在Silverlight中做单元测试,如果你的客户端Silverlight代码里面调用了WCF RIA Service里面的标记有[RequiresAuthentication]的DomainService,那么你在单元测试这些代码的时候就会有麻烦,因为调用这些DomainService会报错,需要Authentication。(有关Enalbe Authentication in WCF RIA Service可以参考这个MSDN页面)

测试任何调用[RequiresAuthentication] DomainService的类都会遇到这个问题,例如ViewModel

有人说你问什么要测标记有[RequiresAuthentication]的DomainService? 测DomainService逻辑用基本方法就可以了,测[RequiresAuthentication]也没有必要。是的,没错,但是你测试Silverlight的ViewModel可以吗?ViewModel里面调用了[RequiresAuthentication]的DomainService的方法你就不测了吗?如果回答是肯定的,那么你就绕不开这个问题。

举个例子,Silverlight应用用MVVM模式来开发,而我们把关于DomainContext调用WCF RIA Service的部分都从ViewModel分离出去,到Service里面。这样的话我们的Service就会用DomainContext来调用WCF RIA Service,如果RIA Service启用了Authentication,也就是WCF RIA Service里面的标记有[RequiresAuthentication]的DomainService,那么我们测试Service就会失败,因为需要Authenciation。同样,你如果没有Service层而直接把那部分逻辑放到ViewModel中,那么你的ViewModel也是不可测试的。除非你绕开这个问题,用Mock对象,但WCF RIA Service是异步的,模拟的真实度有问题。总之,我们需要搞定Authtication的问题,而不是企图绕开问题。

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 )    

 

 以上是当你的代码调用WCF RIA Service的[RequireAuthentication]的DomainService,测试就会报这个错了

2011-07-14 11h16_07

 

标记有[RequiresAuthentication]的DomainService的例子

 1: [EnableClientAccess()]
 2: [RequiresAuthentication()]
 3: public class AdventureWorksDomainService : LinqToEntitiesDomainService<AdventureWorksLT_DataEntities>
 4: {
 5:  [RequiresRole("Managers")]
 6:  public IQueryable<Customer> GetCustomers()
 7:  {
 8:  return this.ObjectContext.Customers;
 9:  }
 10:  
 11:  public IQueryable<Product> GetProducts()
 12:  {
 13:  return this.ObjectContext.Products;
 14:  }
 15:  
 16:  public IQueryable<SalesOrderHeader> GetSalesOrderHeaders()
 17:  {
 18:  return this.ObjectContext.SalesOrderHeaders;
 19:  }
 20: }

 

解决RequireAuthentication的办法

其实思路很明确,就是测试程序一起来就调用用户登录,然后才跑测试用例!

 

解决办法第一步:配置App.xaml删除LifetimeObjects

删除测试工程的App.xaml的如下内容

 1: <Application.ApplicationLifetimeObjects>
 2:  <app:WebContext>
 3:  <app:WebContext.Authentication>
 4:  <appsvc:FormsAuthentication />
 5:  </app:WebContext.Authentication>
 6:  </app:WebContext>
 7: </Application.ApplicationLifetimeObjects>

 

解决办法第二步:添加Partial WebContext类

在测试工程的App.Xaml.cs添加一个类

 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 }

 

解决办法第三步:手工创建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     //添加如下代码:************************************
10     WebContext webcontext = new WebContext();//这个是我们刚创建的WebContext
11     webcontext.Authentication = new System.ServiceModel.DomainServices.Client.ApplicationServices.FormsAuthentication();
12     this.ApplicationLifetimeObjects.Add(webcontext);
13 }

 

解决办法第四步:测试程序启动就自动Authentication

在测试项目的App.xaml.cs中添加如下代码:

 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;//刚刚创建的WebContext
13     if (!auth.IsLoggingIn)
14     {
15         auth.Login(new LoginParameters("yourusername""yourpassword"falsenull), LoginCompleted, null);
16     }
17 
18     //测试页面等登录完成以后再呈现
19     //RootVisual = UnitTestSystem.CreateTestPage();
20 }
21 
22 private void LoginCompleted(LoginOperation loginOperation)
23 {
24     if (loginOperation.LoginSuccess)
25     {
26         //登录成功呈现测试页面
27         RootVisual = UnitTestSystem.CreateTestPage();
28     }
29 }

 

总结

整个过程非常简单,这样以后我们就可以很方便地测试任何调用需要认证的domain service的类和方法了。(:如果你不懂Silverlight单元测试、WCF RIA Service、DomainService、RIA Authentication、WebContext、MVVM模式等阅读本文可能会云里雾里,您可以先看看我的本系列其它文章。)

抱歉!评论已关闭.