I read Andrew's post Dependency Injection/Mocks, what's best? and I wrote my answer and how we use Mock in a project I’m currently working on.
One solution that I use in a current project that works perfect is to pass the mock object into the objects constructor (A constructor only used for mock objects and testing purpose):
CustomerDAMock customerDA = new CustomerDAMock();
CustomerRepository customerRepository = new CustomerRepository(customerDA);
If I use the default constructor I use the real data access class instead. Together with this solution that I think is very common; you can use (Dependency Injection) DI, and use tools that support that, for example Spring.Net to make sure you doesn’t need to write the "Injection". You can also use a Factory to simplify the work. The only thing that I didn’t like in the beginning is to have a special constructor for testing purpose only, but after a while I got used to it. Testing is so important and because of that I think it's also important to design a solution for supporting testing in an easy way (But should not break the domain model and make the model bad).
If you don't like to pass the Mock object to a constructor you can of course use a provider based solution where one provider can be the Mock and the other the real data access object. But with that kind of solution it can be difficult to simulate updates, deletes and inserts etc (Note: “can”, I didn’t say that you can’t).
If you have a Façade that should call several different businesses method and you want to pass a Mock to the Façade. You will need to use several parameters of the façade constructor to pass the Mock object (Can of course use properties but I think it’s more elegant with constructor). For example:
CustomerDAMock customerDA = new CustomerDAMock();
//Add test data to the customer mock object
...
CountryDAMock countryDA = new CountryDAMock();
//Add test data to the country mock object
...
AgreementFacade agreementFacade = new AgreementFacade(customerDA, countryDA);
The example above need to pass the Mock object to make sure all the façade’s business objects will use the mock object’s test data. If there are going to be several Mock object that need to be passed to the façade, we need to create a parameter for each Mock object. Maybe we have 10 Mock objects that we need to pass with test data, which will be a lot of parameters and make the code ugly (My opinion). Instead of that you can use a “context” class (I collogue to my showed me that). You create an interface that will have a property for each data access object you have. Create two new classes, one for the Mock objects and one for the data access classes that implements the interface. For example:
public interface IDataAccessContext
{
ICustomerDA CustomerDA
{
get;
}
ICountryDA CountryDA
{
get;
}
...
}
//The mock context
public class MockContext : IDataAccessContext
{
private ICustomerDA _customerDA;
private ICountryDA _countryDA;
...
public ICustomerDA CustomerDA
{
get
{
if (this._customerDA == null)
this._customerDA = new CustomerDAMock();
return this._customerDA;
}
}
public ICountryDA CountryDA
{
get
{
if (this._countryDA == null)
this._ countryDA = new CountryDAMock();
return this._ countryDA;
}
}
....
}
//The Data access context
//The mock context
public class DAContext : IDataAccessContext
{
private ICustomerDA _customerDA;
private ICountryDA _countryDA;
...
public ICustomerDA CustomerDA
{
get
{
if (this._customerDA == null)
this._customerDA = new CustomerDA();
return this._customerDA;
}
}
public ICountryDA CountryDA
{
get
{
if (this._countryDA == null)
this._ countryDA = new CountryDA();
return this._ countryDA;
}
}
...
}
When you are done with the context classes you instead add only one single parameter to the constructor that will take the mock object. The parameter is of type IDataAccessContext. By doing that you only need to pass one object to the constructor that will only instantiate the Mock object that you need to use:
MockContext mockContext = new MockContext():
//Add test data to the customer mock object
mockContext.CustomerDA.InesertCustomer(...)
//Add test data to the country mock object
mockContext.CountryDA.InsertCountry(...)
AgreementFacade agreementFacade = new AgreementFacade(mockContext);
Now you maybe wonder why the DataAccessContext exists. It can simplify the code a little bit of the façade; take a look at the following example:
Public class AgreementFacade
{
private IDataAccessContext _dataAccessContext;
public AgreementFacade()
{
this._dataAccessContext = new DataAccessContext();
}
public AgreementFacade(IDataAccessContext mockContext)
{
this._dataAccessContext = mockContext;
}
public void CreateAgreement(...)
{
this._dataAccesContext.CountryDA.GetCountry(...);
this._dataAccessContex.AgreementDA.CreateAgreement(...);
}
}
As you can see in the example above the default constructor will instantiate the DataAccessContext with the real data access objects and set the private _dataAccessCotext field with the data access context. The constructor with the mockContext will set the private _dataAccessContext with the mock context. You can now simply use the context classes to get the correct data access object or Mock object and your code doesn’t need to “extract” the Mocks from the context into its own variables.
If you have any comments or ideas how to make it even better, I would like to here from you. Please don’t hesitate to contact me.