So Many Projects!
Friday, April 28th, 2006
I noticed today that I work with a lot of build projects. We have some where close to 70 build projects all using CI Factory. I think this shows that CI Factory is a proven design. It is a scalable product.

I noticed today that I work with a lot of build projects. We have some where close to 70 build projects all using CI Factory. I think this shows that CI Factory is a proven design. It is a scalable product.

Shawn Riesterer has a nice post on Build Machine Virtualization. The build team where I work is dipping their toe in the pool. I have jumped in myself. In fact this weekend I will be making the build servers for CI Factory, Doubler, and Refly publicly avalible. I built them in a virtual machine on my laptop and will transfering the image to my fathers web server on Saturday.
The dev team at work has started maintaining virtual images for all supported versions of our flagship product. This helps keep how it takes to transition between branches down as well as getting new developers up, running and productive.
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;
}
}
}
}
}