Controlling Base Class Behavior
Ignoring Base Class Constructor
When creating fake objects you sometimes need to call the object's real
constructor, but not call its base class constructor. This is useful
when the fake object's constructor performs initializations required
for the test, but the base classes have external dependencies in their
construction which should be faked. This is done by defining
constructor and base constructor behavior in Isolate.Fake.Instance().
Example: the TopCustomerData object inherits a base class which has a
dependency in a database connection (see code at the bottom). We
want to create a fake object out of Customers, but avoid calling the
base class constructor as it would try to connect to the external
database. This is done by specifying the class' constructor will be
called, while its base constructor will be ignored:
[TestMethod, Isolated]
public void FakeBaseClassConstructor_FakeBaseClassWhichThrowsOnCtor()
{
// fake data manipulations on DataAccess
var fakeDataAccess = Isolate.Fake.Instance<DataAccess>();
Isolate.WhenCalled(() => fakeDataAccess.GetTopCustomer(null)).WillReturn(new Customer() {Name = "test"});
Isolate.Swap.NextInstance<DataAccess>().With(fakeDataAccess);
// create an instance of TopCustomerData that will behave like a normal instance, but avoid calling the base class constructor
var customerData = Isolate.Fake.Instance<TopCustomerData>(Members.CallOriginal, ConstructorWillBe.Called,
BaseConstructorWillBe.Ignored);
// verify the top customer is the same one that data access returned
Assert.AreEqual("test", customerData.GetCustomer().Name);
}
A TypeMockException will be
thrown if you are trying to fake base constructor behavior on types
which are not inherited (i.e inherit from System.Object) or classes
that inherit from mscorlib types
You cannot fake base class behavior on interfaces as they don't inherit from concrete base classes
Instead of always faking the immediate base class constructor, we
can define at which level in the hierarchy the constructor will be
faked. All constructors from the class being faked up to the defined
base type will be called, and the constructor of the defined type (and
all types it inherits from) will be faked. This is done by providing Isolate.Fake.Instance()
with the base type to fake. A TypeMockException will be thrown if the
base class to ignore is not in the inheritance chain of the faked type.
These are the test classes used in this example:
abstract class RepositoryBase
{
protected static DataTable table;
public RepositoryBase()
{
PopulateData(table);
}
protected void PopulateData(DataTable dataTable)
{
// implementation will rely on an external data connection
throw new NotImplementedException();
}
}
class TopCustomerData : RepositoryBase
{
private Customer customer;
protected static DataAccess dataAccess;
public TopCustomerData()
{
dataAccess = new DataAccess(table);
customer = dataAccess.GetTopCustomer(table);
}
public Customer GetCustomer()
{
return customer;
}
}
public class DataAccess
{
public DataAccess(DataTable table)
{
}
public Customer GetTopCustomer(DataTable table)
{
throw new NotImplementedException();
}
}
Copyright © Typemock
Ltd.
2004-2010. All Rights Reserved.