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:
public 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
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.
Chris, I don't have the Validator Running as a component in the container, so I haven't run into it.
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.
Chris,
I did something similar, except that I used MarkMissing() ;-)
Comment preview