View Integration Tests with Spring 2.5

Over the past few months I’ve spent a fair amount of time with the Spring 2.5 annotation-based integration test support and have by and large been impressed. The combination of the @ContextConfiguration and @Transactional annotations with Autowiring makes most integration tests easy to write and read. Add in the support for caching of an ApplicationContext once it’s been loaded once and the benefit to cost ratio looks much rosier for most integration tests.

However, I recently tried to write a regression test against the output of a view (in this case a Velocity template, but it’s a general issue) and came across an exception:

WebApplicationObjectSupport instance [lengthy name of view] does not run in a WebApplicationContext but in: org.springframework.context.support.GenericApplicationContext

A quick google revealed others with the same problem, but no obvious solution. Eventually I did manage to work round the problem, but the scaffolding I had to bodge together in order to get it to work is far from pretty:

First create a new WebApplicationContext

public class GenericWebApplicationContext
	extends GenericApplicationContext
	implements WebApplicationContext {

	public ServletContext getServletContext() {
		MockServletContext servletContext =
			new MockServletContext();
		servletContext.setAttribute(
				ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this);
		return servletContext;
	}
}

So far, not so bad. The problem comes in that the critical part in creating an ApplicationContext via the annotation driven approach is that the loadContext method in AbstractGenericContextLoader simply news up a GenericApplicationContext and is final, so in order to create a ContextLoader that creates a GenericWebApplicationContext you have to copy and paste AbstractGenericContextLoader in to a new class then change

final GenericApplicationContext context = new GenericApplicationContext();

to

final GenericApplicationContext context = new GenericWebApplicationContext();

then duplicate GenericPropertiesContextLoader or GenericXmlContextLoader, with no code changes except to specify a different parent class.

If you then specify that loader in your @ContextConfiguration you should be able to run tests that include executing views.

It’s a testament to the readability of Spring’s code and one of the great advantages of using an open source framework that I was able at all to create a workaround for this, but obviously this is far from ideal and a framework change to be able to override the context created, or a simple way of specifying by annotation that you wanted a WebApplicationContext would be far preferable.

There’s an existing issue outstanding for this, so if like me you’d rather not resort to such hackery, then please add your vote.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s