Mocking RIA Services Authentication and Authorization

I’m about to embark on a series of Silverlight Authorization-related posts using a shared sample project. I use this base project as a template to share functionality and visual consistency to my sample applications. Most of the template is pretty straightforward. I have a MasterPage that imports (using MEF) a few different things for each sample application. The most interesting of these is the list of Users the sample will be working against. The template puts these users in a ListBox, and when a user is selected in the list, the template updates WebContext.Current.User.

In updating WebContext.Current.User, the template uses a MockAuthentication type. Mocks of this kind are very useful as they allow you to test how your Silverlight application behaves in response to different user credentials. In each of my (upcoming) samples, you can cycle through the different users and see how the applications change.

The first step in creating a mock is extending the AuthenticationService type found in the System.ServiceModel.DomainServices.Client assembly. At a minimum you’ll need to implement the CreateDefaultUser method and at least one authentication operation (I chose LoadUser).

   public class MockAuthentication : AuthenticationService
  {
      public static IPrincipal MockUser { get; set; }

      private readonly IPrincipal _defaultUser;

      public MockAuthentication(IPrincipal defaultUser)
      {
          this._defaultUser = defaultUser;
      }

      protected override IPrincipal CreateDefaultUser()
      {
          return this._defaultUser;
      }

      protected override IAsyncResult BeginLoadUser(AsyncCallback callback, object state)
      {
          IAsyncResult result = new MockAsyncResult(state);
          Deployment.Current.Dispatcher.BeginInvoke(
              () => callback(new MockAsyncResult(state)));
          return result;
      }

      protected override LoadUserResult EndLoadUser(IAsyncResult asyncResult)
      {
          return new LoadUserResult(MockAuthentication.MockUser);
      }

      // ...

      private class MockAsyncResult : IAsyncResult
      {
          private readonly object _asyncState;

          public MockAsyncResult(object asyncState)
          {
              this._asyncState = asyncState;
          }

          public object AsyncState { get { return this._asyncState; } }
          public WaitHandle AsyncWaitHandle { get { throw new NotImplementedException(); } }
          public bool CompletedSynchronously { get { return false; } }
          public bool IsCompleted { get { return true; } }
      }
  } 

The next step is to add the the mock AuthenticationService to the WebContext. In your test App constructor, just add the following lines.

   this.ApplicationLifetimeObjects.Add(new WebContext()
      {
         Authentication = new MockAuthentication(myDefaultUser)
      });

Finally, in your test code you can select the user you want to test in just another few lines.

   MockAuthentication.MockUser = myTestUser;
  WebContextBase.Current.Authentication.LoadUser();

Calling the LoadUser method will result in an asynchronous update to WebContext.Current.User. It also correctly raises a LoggedIn or LoggedOut event from WebContext.Current.Authentication. This not only allows you to test different application states, but also to test application transitions simulating every time a new user signs in or signs out.