April 26, 2006 Uncategorized

Mocking Static Classes and Members

There have been some recent posts on mocking statics. Static members that is and I remember an older post on mocking a static class. This is all do able if you use indirection. For a static member you can use a delegate to provide the indirection. I will try to keep with Steve Eichert’s example.

 

public abstract class BaseEntity<T>
{
    protected delegate List<T> FindAllWork();
 
    protected static FindAllWork FindAllWorker;
 
    protected static IDatabase<T> db = new Database<T>();
 
    public SaveObjectResponse Save()
    {
        return db.Save(this);
    }
 
    public bool Delete()
    {
        return db.Delete(this);
    }
 
    public static List<T> FindAll()
    {
        if (FindAllWorker == null)
            FindAllWorker = new FindAllWork(DefaultFindAllWorker);
        return FindAllWorker();
    }
 
    protected static List<T> DefaultFindAllWorker()
    {
        return db.FindAll();
    }
}
 
public abstract class MockableEntity<T> : BaseEntity<T>
{
    public MockableEntity()
    {
        BaseEntity<T>.FindAllWorker = new BaseEntity<T>.FindAllWork(this.FindAllPassThrough);
    }
 
    public List<T> FindAllPassThrough()
    {
        return BaseEntity<T>.db.FindAll();
    }
}

I don’t use dynamic mocking myself but I think that should work. If you want to state an expectation that FindAll is being called you would expect FindAllPassThrough to be called. The principle to take note of is that we are wrapping a static call in an instance call. In fact we are not changing the static interface that the client knows we are just wrapping the the work done by that static call in an instance. You can apply this principle to an entire class as well. 
 

public static class StaticSingleton
{
    private static IWrapper _Wrapper;
 
    public static IWrapper Wrapper
    {
        get
        {
            if (_Wrapper == null)
                _Wrapper = new TheRealDeal();
            return _Wrapper;
        }
        set
        {
            _Wrapper = value;
        }
    }
 
    public static void DoSomething()
    {
        Wrapper.DoSomething();
    }
}
 
public interface IWrapper
{
    void DoSomething();
}
 
public class TheRealDeal : IWrapper
{
    public void DoSomething()
    {
        Console.WriteLine("Hello, World");
    }
}

Below is an example unit test using a recording test stub generated by Doubler and below that the recording test stub. 
 

namespace Double
{
    using System;
 
    public class RecorderIWrapper : IWrapper
    {
 
        private IWrapperRecordings _recordings;
 
        public RecorderIWrapper()
        {
            this.Recordings.NewRecording.Called = true;
            if ((this.Recordings.NewRecording.ExceptionToThrow != null))
            {
                throw this.Recordings.NewRecording.ExceptionToThrow;
            }
        }
 
        public virtual IWrapperRecordings Recordings
        {
            get
            {
                if ((this._recordings == null))
                {
                    this._recordings = new IWrapperRecordings();
                }
                return this._recordings;
            }
            set
            {
                this._recordings = value;
            }
        }
 
        public void DoSomething()
        {
            this.Recordings.DoSomethingRecording.Called = true;
            if ((this.Recordings.DoSomethingRecording.ExceptionToThrow != null))
            {
                throw this.Recordings.DoSomethingRecording.ExceptionToThrow;
            }
        }
 
        public class IWrapperRecordings
        {
 
            private NewRecordingRecordings _newRecording;
 
            private DoSomethingRecordingRecordings _doSomethingRecording;
 
            public virtual NewRecordingRecordings NewRecording
            {
                get
                {
                    if ((this._newRecording == null))
                    {
                        this._newRecording = new NewRecordingRecordings();
                    }
                    return this._newRecording;
                }
                set
                {
                    this._newRecording = value;
                }
            }
 
            public virtual DoSomethingRecordingRecordings DoSomethingRecording
            {
                get
                {
                    if ((this._doSomethingRecording == null))
                    {
                        this._doSomethingRecording = new DoSomethingRecordingRecordings();
                    }
                    return this._doSomethingRecording;
                }
                set
                {
                    this._doSomethingRecording = value;
                }
            }
        }
 
        public class DoSomethingRecordingRecordings
        {
 
            private bool _called;
 
            private System.Exception _exceptionToThrow;
 
            public virtual bool Called
            {
                get
                {
                    return this._called;
                }
                set
                {
                    this._called = value;
                }
            }
 
            public virtual System.Exception ExceptionToThrow
            {
                get
                {
                    return this._exceptionToThrow;
                }
                set
                {
                    this._exceptionToThrow = value;
                }
            }
        }
 
        public class NewRecordingRecordings
        {
 
            private bool _called;
 
            private System.Exception _exceptionToThrow;
 
            public virtual bool Called
            {
                get
                {
                    return this._called;
                }
                set
                {
                    this._called = value;
                }
            }
 
            public virtual System.Exception ExceptionToThrow
            {
                get
                {
                    return this._exceptionToThrow;
                }
                set
                {
                    this._exceptionToThrow = value;
                }
            }
        }
    }
}

10,766 Total Views

Leave a comment

*

here