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.
0 responses so far ↓
There are no comments yet...Kick things off by filling out the form below.