• Home
  • About Me

.Net Braindrops

… where thoughts become excecutable.

Feeds:
Posts
Comments

How to make ASP.net session state testable

May 19, 2008 by Lars Corneliussen

  • If you’ve read my Article about How to wrap the ASP.net session state I want to show you how to make the wrapper testable using the Free .Net Ambient Context Pattern Implementation.
  • If you only want a easy ASP.net session state wrapper snippet without any dependencies, try How to wrap the ASP.net session state

In the initial version, the wrapper simply throws an exception if HttpContext.Current or HttpContext.Current.Session is not available.

So in our Test-Methods we have to “mock” out the SessionState somehow. Basically we just need to override the Session State with a static dictionary within the computing Thread.

I would like to write my tests like this…

[Test]
public void TestOverride()
{
  using(SessionVariableStorage.Override(new Dictionary<string, object>()))
  {
    // normally a call to code that uses session variables internally
    var sessionString = new SessionVariable("sessionString");
    Assert.IsFalse(sessionString.HasValue);
    sessionString.Value = "Hello, world!";
    Assert.IsTrue(sessionString.HasValue);
    Assert.AreEqual("Hello, world!", sessionString.Value);
  }
}

To enable that, I need an extra static class “SessionVariableStorage” and some modifications in the SessionVariable<T>.

public static class SessionVariableStorage
{
  internal static readonly ThreadVariable<IDictionary<string, object>> Storage =
    new ThreadVariable<IDictionary<string, object>>();

  public static IDisposable Override(IDictionary<string, object> storage)
  {
    return Storage.Use(storage);
  }
}

Every time before I access the HttpSession I have to check wether it’s currently overridden or not. Here is the new version (requiring ThreadVariable<T>)

/// <summary>
/// Wrapper class for <see cref="HttpContext.Session"/>.
/// Author: Lars Corneliussen
/// Source: http://startbigthinksmall.wordpress.com/2008/05/14/how-to-wrap-the-aspnet-session-state/
/// </summary>
/// <typeparam key="T">
/// The type of the value to be stored.
/// </typeparam>
public class SessionVariable<T>
{
  private readonly string key;
  private readonly Func<T> initializer;

  /// <summary>
  /// Initializes a new session variable.
  /// </summary>
  /// <param name="key">
  /// The key to use for storing the value in the session.
  /// </param>
  public SessionVariable(string key)
  {
    if (string.IsNullOrEmpty(key))
      throw new ArgumentNullException("key");

    this.key = GetType() + key;
  }

  /// <summary>
  /// Initializes a new session variable with a initializer.
  /// </summary>
  /// <param name="key">
  /// The key to use for storing the value in the session.
  /// </param>
  /// <param name="initializer">
  /// A function that is called in order to create a
  /// default value per session.
  /// </param>
  public SessionVariable(string key, Func<T> initializer) : this(key)
  {
    if (initializer == null)
      throw new ArgumentNullException("initializer");

    this.initializer = initializer;
  }

  private object GetInternalValue(bool initializeIfNessesary)
  {
    if (SessionVariableStorage.Storage.HasCurrent)
    {
      var dictionary = SessionVariableStorage.Storage.Current;

      object value;

      if (!dictionary.TryGetValue(key, out value) && initializeIfNessesary
          && initializer != null)
        dictionary.Add(key, value = initializer());

      return value;
    }
    else
    {
      HttpSessionState session = CurrentSession;

      var value = session[key];

      if (value == null && initializeIfNessesary
          && initializer != null)
        session[key] = value = initializer();

      return value;
    }
  }

  private static HttpSessionState CurrentSession
  {
    get
    {
      var current = HttpContext.Current;

      if (current == null)
        throw new InvalidOperationException(
          "No HttpContext is not available.");

      var session = current.Session;
      if (session == null)
        throw new InvalidOperationException(
          "No Session available on current HttpContext.");
      return session;
    }
  }

  /// <summary>
  /// Indicates wether there is a value present or not.
  /// </summary>
  public bool HasValue
  {
    get { return GetInternalValue(false) != null; }
  }

  /// <summary>
  /// Sets or gets the value in the current session.
  /// </summary>
  /// <exception cref="InvalidOperationException">
  /// If you try to get a value while none is set.
  /// Use <see cref="ValueOrDefault"/> for safe access.
  /// </exception>
  public T Value
  {
    get
    {
      object v = GetInternalValue(true);

      if (v == null)
        throw new InvalidOperationException(
          "The session does not contain any value for '"
          + key + "'.");

      return (T) v;
    }
    set
    {
      if (SessionVariableStorage.Storage.HasCurrent)
        SessionVariableStorage.Storage.Current.Add(key, value);
      else
        CurrentSession[key] = value;
    }
  }

  /// <summary>
  /// Gets the value in the current session or if
  /// none is available <c>default(T)</c>.
  /// </summary>
  public T ValueOrDefault
  {
    get
    {
      object v = GetInternalValue(true);

      if (v == null)
        return default(T);

      return (T)v;
    }
  }

  /// <summary>
  /// Clears the value in the current session.
  /// </summary>
  public void Clear()
  {
    if (SessionVariableStorage.Storage.HasCurrent)
      SessionVariableStorage.Storage.Current.Remove(key);
    else
      CurrentSession.Remove(key);
  }
}


Possibly related posts: (automatically generated)

  • How to wrap the ASP.net session state

Posted in dotnet | Tagged Application, ASP.Net, HttpApplicationState, HttpSessionState, Page, Session, Session State, TDD, Testable Code, Type Safe, Wrapper | 1 Comment

One Response

  1. on May 19, 2008 at 19:05 How to wrap the ASP.net session state « .Net Braindrops

    [...] I wrote an newer version which has more dependencies, but is suitable for UnitTesting (How to make ASP.net session state testable) [...]



Comments are closed.

  • I’m a passionate clean code developer working as consultant with itemis, Germany. My main interest within programming is software principles and model driven software development.
  • Posts

    • November 2009 (2)
    • October 2009 (1)
    • September 2009 (1)
    • August 2009 (3)
    • July 2009 (2)
    • June 2009 (3)
    • May 2009 (5)
    • April 2009 (4)
    • March 2009 (4)
    • February 2009 (4)
    • January 2009 (2)
    • December 2008 (3)
    • November 2008 (6)
    • October 2008 (7)
    • September 2008 (1)
    • August 2008 (4)
    • June 2008 (3)
    • May 2008 (5)
    • April 2008 (3)
  • Tags

    .NET Application ASP.Net c# check codegeneration code highlighting dotnet DSL Dublin Eclipse extension methods german HttpApplicationState HttpSessionState javascript jQuery M mdsd mdsd+.net MGrammar MGraph microsoft Microsoft "M" Microsoft Oslo Modeling MSchema oaw oslo Oslo Repository Page PDC08 PDC2008 Quadrant R# Resharper Session Session State TDD Type Safe visual studio visualstudio wf Wrapper xtext
  • Top Posts

    • beautyOfCode: jQuery Plugin for Syntax Highlighting
    • beautyOfCode – jQuery plugin for Syntax Highlighter 2.0 by Alex Gorbatchev
    • Behind the scenes of the C# yield keyword
    • How to wrap the ASP.net session state
  • My del.icio.us

  • Blog Stats

    • 73,902 hits
  • Search

  • Meta

    • Log in
    • Entries RSS
    • Comments RSS
    • WordPress.com
  • My twitter updates

    • Get to go to bed now! It's 10:25 am on my biological clock. And yet allready 1:25 in L.A. Good night twitter-world! #pdc09 - 2 hours ago
    • Which tag should we pick for the #oslo / #msoslo stuff? #sqlmodelling? #msmodelling? #msoslo? #sqlservermodelling? #m? - 2 hours ago
    • http://tr.im/F3ms Go to the end to see "M" in eclipse. Nice. #msoslo #sqlmodelling - 2 hours ago
    • Looks pretty much like an ecore-model plus TCS for M. http://tr.im/F3mb #msoslo #sqlmodelling - 2 hours ago
    • @donbox @douglasp @csells I think this really is what many experienced: http://tr.im/F3jr - 2 hours ago

Blog at WordPress.com.

Theme: Mistylook by Sadish.