Ayende @ Rahien

Refunds available at head office

The Auto Mocking Container

Several months ago the guys from Eleutian released the Auto Mocking Container, a combination of Rhino Mocks and Windsor container. I looked at it at the time, and I liked it, but I didn't really get a chance to work with it until recently.

You can see how a non trivial controller may look like on the left. It has a fair number of collaborators, for data access, logging, notifications, etc.

This approach make building the controller very easy:

imagepublic void DisplayOrdersForApproval()
{
	if (AuthorizationService.AllowedToApproveOrders() == false)
		AccessForbidden();

	PropertyBag["orders"] = Orders.FindAll(
		Where.Order.Status == OrderStatus.WaitingForApproval &&
		Where.Order.Department == CurrentUser.Department
		);
}

public void RejectOrder(Order order)
{
	NotificationService.OrderRejected(order);
	Logger.Info("User {0} had rejected order {1}.", 
		CurrentUser.Name, order.Id);
	order.Stutus = OrderStatus.Rejected;
	Orders.Save(order);
}

public void ShipOrder(Order order)
{
	NotificationService.StartedOrderShipping(order);
	Logger.Info("User {0} had approved order {1}.",
		CurrentUser.Name, order.Id);
	ShippingService.Ship(order);
}

 

The controller is merely coordinating the work of services in the application, which is what I think it should do. But how do I test such a thing? Setting up seven collaborators per tests is a PITA, and it gets worse if you consider additional dependencies that may be required by the base class.

Enter the Auto Mocking Container, which makes all of this a real pleasure, check this out:

[Test]
public void RejectingAnOrderWillSendNotification()
{
	AutoMockingContainer container = new AutoMockingContainer(Mocks);
	OrderApprovalController controller = container.Create<OrderApprovalController>();
	Order order = new Order();
	INotificationService mockedNotificationService = container.Resolve<INotificationService>();

	using (Mocks.Replay())
	{
		mockedNotificationService.OrderRejected(order);
	}
	using (Mocks.Playback())
	{
		controller.RejectOrder(order);
	}
}

There are a lot of interesting options on the Auto Mocking Container that I suggest that you will check out. I really like it.

Comments

Chris Ortman
06/12/2007 03:06 PM by
Chris Ortman

Did you run into any problems with ValidatorRunner? When I tried to use this with controllers it kept trying to create the validator runner which doesn't have a default constructor and would fail.

Ayende Rahien
06/12/2007 03:49 PM by
Ayende Rahien

Chris, I don't have the Validator Running as a component in the container, so I haven't run into it.

Chris Ortman
06/12/2007 04:11 PM by
Chris Ortman

What I ran into was that the AutoMockingContainer would detect the ValidatorRunner as a dependency of the Controller (because it is a public writeable property on Controller) and try to resolve the dependency by creating a mock which fails because no ctor args are passed to the call to DynamicMock<>

I wound up modifying the AutoMockingDependencyResolver to return false if the mocking strategy is "NonMocked" so that the container could decide it was an optional dependency and ignore it.

Ayende Rahien
06/12/2007 05:04 PM by
Ayende Rahien

Chris,

I did something similar, except that I used MarkMissing() ;-)

Comments have been closed on this topic.