Saturday, January 24, 2009

Implementing and testing mapping code with AutoMapper

I was thinking some months ago that it would be great to have a property mapper that eliminates tedious mapping code . I'm very happy that Jimmy Bogard and his team just have published a framework called AutoMapper that resolves that issue. I haven't tested it yet but the idea looks promising.

Why would I use AutoMapper?
  • In order to implement better encapsulation and layering with less amount of coding
  • In order to unit-test mapping code using a simple 'Mapper.AssertConfigurationIsValid()'

Sunday, January 11, 2009

TypeMockAutoMocker on CodePlex

I' ve just uploaded the TypeMockAutoMocker to http://www.codeplex.com/typemockautomocker

How to use it:
1.) Download TypeMockAutoMocker.dll
2.) Copy it to your project and set an assembly reference to it
2.) Set 'Copy local = true' on your TypeMock.dll
3.) Have fun (see Link)

StructureMap 2.5.1 and TypeMock 5.1.2 ist the only tested configuration at the moment.

Friday, January 2, 2009

AutoMocking Container with TypeMock Isolator

I have implemented an AutoMocking container for the Isolator inspired by an Introduction to the AutoMocking container in StructureMap, the fact that our test setups usually are pretty messy and Jeremy's claim that TypeMock users probably don't care about dependency injection. But why do I want to use DI (Dependency Injection) in conjunctions with TypeMock? I don't want to fight a 'religious war' based on that question, but here is what I think:

  • TypeMock without DI lacks an explicit boundary that defines what the class under tests is and which classes are mocks or stubs. This is about solid design and to isolate parts of the software in a structured manner. It’s true that you can mock everything with TypeMock but this is just about mocking and not about software design.

  • DI with another mocking framework than TypeMock is like .NET without System.Reflection. I don't like to use System.Reflection but sometimes it's just the right thing. It’s the same with TypeMock. If everything (own code, legacy-code, external libraries etc.) had a solid design you wouldn't need it but sometime it makes the life so much easier.
Example without Dependency Injection
There is the class under test called ValidationViewPresenter and it has following dependencies:



A a test without DI could look like:
[Test]
public void CanValidateCreditCardNumber()
{
// Arrange
var viewMock = Isolate.Fake.Instance<ValidationView>();
var customerServiceMock = Isolate.Fake.Instance<CustomerService>();
var creditCardServiceMock = Isolate.Fake.Instance<CreditcardService>();
var customer56 = new Customer {CreditCardNr = "5500 0001 0001 0001"};

// Mock the (hidden) dependencies
Isolate.Swap.NextInstance<ValidationView>().With(viewMock);
Isolate.Swap.NextInstance<CustomerService>().With(customerServiceMock);
Isolate.Swap.NextInstance<CreditcardService>().With(creditCardServiceMock);
// Mock the calls to the dependencies
Isolate.WhenCalled(()=>viewMock.CustomerNr).WillReturn(56);
Isolate.WhenCalled(() => customerServiceMock.GetCustomer(56)).WillReturn(customer56);
Isolate.WhenCalled(()=> creditCardServiceMock.ValidateCreditCard("5500 0001 0001 0001")).WillReturn(true);

// Act
  var presenter = new ValidationViewPresenter();

presenter.ValidateCreditCardOfCustomer();
// Assert
Isolate.Verify.WasCalledWithExactArguments(() => viewMock.IsValid = true);
}

Example with Dependency Injection
After introducing constructor injection it looks like:
[Test]
public void CanValidateCreditCardNumber()
{
// Arrange
var viewMock = Isolate.Fake.Instance<ValidationView>();
var customerServiceMock = Isolate.Fake.Instance<CustomerService>();
var creditCardServiceMock = Isolate.Fake.Instance<CreditcardService>();
var customer56 = new Customer {CreditCardNr = "5500 0001 0001 0001"};
// Inject dependencies manually
  var presenter = new ValidationViewPresenter(viewMock, customerServiceMock, creditCardServiceMock);

Isolate.WhenCalled(()=> viewMock.CustomerNr).WillReturn(56);
Isolate.WhenCalled(() => customerServiceMock.GetCustomer(56)).WillReturn(customer56);
Isolate.WhenCalled(() => creditCardServiceMock.ValidateCreditCard("5500 0001 0001 0001")).WillReturn(true);

// Act
presenter.ValidateCreditCardOfCustomer();

// Assert
Isolate.Verify.WasCalledWithExactArguments(() => viewMock.IsValid = true);
}

Example with Automocking Container
Let's eliminate the explicit constructor injection by introducing the TypeMockAutoMocker now:

[Test]
public void CanValidateCreditCardNumber()
{
// Arrange
var customer56 = new Customer {CreditCardNr = "5500 0001 0001 0001"};
  var presenterMocker = new TypeMockAutoMocker<ValidationViewPresenter>(MockMode.AAA);

var viewMock = presenterMocker.Get<IValidationView>();
var customerServiceMock = presenterMocker.Get<ICustomerService>();
var creditCardServcieMock = presenterMocker.Get<ICreditCardService>();

Isolate.WhenCalled(() => viewMock.CustomerNr).WillReturn(56);
Isolate.WhenCalled(() => customerServiceMock.GetCustomer(56)).WillReturn(customer56);
Isolate.WhenCalled(() => creditCardServcieMock.ValidateCreditCard("5500 0001 0001 0001")).WillReturn(true);

// Act
presenterMocker.ClassUnderTest.ValidateCreditCardOfCustomer();

// Assert
Isolate.Verify.WasCalledWithExactArguments(() => viewMock.IsValid = true);
}
As you can see the AutoMocking container couldn’t eliminate a lot of complexity. This is due to the fact that the test itself is complex and there are a number of non-default preconditions.

A better example with AutoMocking Container
Following code tests the same method but with different preconditions again. But this time we can rely on the default behavior that was setup by the AutoMocking container. This means that all involved and not explicitly mocked interfaces or classes do have a default behavior.

[Test]
public void CanHandleNotExistingCustomer()
{
// Arrange
  var presenterMocker = new TypeMockAutoMocker<ValidationViewPresenter>(MockMode.AAA);

var viewMock = presenterMocker.Get<IValidationView>();
Isolate.WhenCalled(() => viewMock.CustomerNr).WillReturn(56);

// Act
presenterMocker.ClassUnderTest.ValidateCreditCardOfCustomer();

// Assert
Isolate.Verify.WasCalledWithExactArguments(() => viewMock.IsValid = false);
}
Conclusion
There is a big chance that you can get lost using TypeMock and StructureMap in conjunction. The problem is that there are too many ways how they can be combined. However I hope that the TypeMockAutoMocker could help in a way that it's defining a common pattern for how to setup the tests and how to inject the mocks. Remember always:
  • Depended classes are instantiated by the AutoMocker automatically.
  • Depended interfaces and abstract classes are instantiated as mocks. These mocks do have a default behaviour where every method can be called.
  • Depended concrete classes are instantiated by calling its greediest constructor. They are not mocked.
  • To change the default behaviour you can use Inject() to register your own mock to the AutoMocker. It's how you can setup a mock manually.

Sound’s like ‘convention over configuration’. And that makes life definitely easier.