Testing MVC Elements and Interactions with Mock Container
Lokad Shared Libraries project includes implementation of the MockContainer that significantly simplifies testing of Model-View-Controller elements in separation. It does this by automatically generating and injecting mock objects, should the tested class ask for them in its constructor.
These mock objects are persisted in the local container instance as singleton, so that additional expectations could be recorded against them. Expectations are verified when the container is disposed.
There is a little overhead of creating and disposing container and instances every test, since we are using Autofac IoC Container internally here, which has a really good performance.
Interface and internals of this MockContainer have been polished heavily since its introduction a few months ago. This (with the help from a base fixture class providing a nice syntax) has allowed to write tests like this one:
[Test]
public void Display()
{
View.SetTitle("Some title");
// we expect the view to ask IViewspace to display itself
WhenViewIsShown
// you always set Form.CancelButton for user's pleasure
.CancelButtonShouldBeSet()
// assert that title as as expected
.TitleShouldBe("Some title");
// create 0 to 20 random models and display them in view
View.BindModel(RandClientModels.NextEvents(0, 20));
}
This is an actual unit test against actual Windows.Forms.UserControl component. It does what it says. Ability to write unit tests like this brings following benefits for free:
- In this unit test all calls are executed against the interface. So should we need add Silverlight or WPF view implementations to our library, we would already have tests for the first step of Test Driven Development.
- Ability to write simple unit tests really pays off in scenarios, where a single component is reused in multiple projects. Finding a bug in one of these projects, expressing it in a unit test and fixing, immediately makes all projects downstream more stable.
- Using randomly-generated Models allows to cover a wider range of the possible failure scenarios. Should some case go wrong, we'll be able to reproduce it by checking out rand seed used in the integration run (Nondeterministic reproducible testing will be the subject of another article).
Here's another type of unit test. It could be invoked explicitly just to see how our view looks alone (without launching an entire application and clicking our way to this View):
[Test, Explicit]
public void Show_view_for_debugging()
{
// when view asks to show itself, actually display it
WhenViewIsShown.ShowAsDialog();
// load random values and display
View.BindModel(RandClientModels.NextEvent());
// display view, while using ValidEvent rule
// to validate all input
View.GetModel(EditEventController.ValidEvent);
}
ExplicitAttribute in NUnit tells us that unit test is excluded from the usual unit testing run and has to be launched manually.
This kind of debugging unit test for the reusable View components speeds up all the testing and UI tweaking process. Do you need to check out how View validates data, scales or displays that recent UI tweak? This is just one click away:

Sometimes we may want to go deeper and check out how various components integrate together. This is not a normal unit test (in the sense of Unit Testing), so it is marked with ExplicitAttribute as well.
[Test, Explicit]
public void Test_for_debugging_with_controller()
{
// view is registered by test fixture
WhenViewIsShown.ShowAsDialog();
// simplified syntax for registering additional components
// that we don't want to be replaced with mock objects.
Container.Build(builder =>
{
builder.Register<ConnectionEditController>();
builder.Register<WorkScopeView>().As<IWorkScopeView>();
});
// resolving controller and launching it with a random connection
var controller = Container.Resolve<ConnectionEditController>();
controller.Startup();
controller.Edit(RandApiModels.NextServiceConnection());
}
Although code like this does not participate in the Continuous Integration process, having it around speeds up the development and simplifies debugging, should something go wrong.
This specific test creates UI elements like this:

Unit tests samples come from open source project Lokad SDK that allows developers to introduce forecasting capabilities of Lokad.com into their applications.
Thursday, June 25, 2009 at 3:38
Reader Comments (1)
I really like your ideas for quick testing UI components. It seems way smarter than relaunching the entire app and then navigate to the corresponding part. I will recycle this idea for my software engineering course next year :-)