Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Write Junit tests for Spring MVC application which internally relies upon ContextLoader.getCurrentWebApplicationContext()

Tags:

spring-mvc

I'm trying to write integration tests for a controller in our spring mvc application. The controller invokes a service class which in turn invokes a dao to read/write data from the repository. The DAO needs to lookup some configuration. The configuration bean is defined in WEB-INF/applicationContext.xml.

I'm using something like this:

Configuration config =(Configuration)ContextLoader.getCurrentWebApplicationContext().getBean("config");
private String namespace = config.getProperty("someproperty");

The properties are stored in zookeeper so I'm not using spring's property management artifacts.

The problem is that while running the JUnit test ContextLoader.getCurrentWebApplicationContext() always returns null.

I have so far looked at the following approaches:
1. Ted Young's approach ( just google search for spring mvc integration tests ted young)
2. https://github.com/SpringSource/spring-test-mvc
3. this site.. questions/8464919/unit-testing-a-servlet-that-depends-on-springs-webapplicationcontextutils-getre
4. Use Selenium/JWebunit
5. http://confluence.highsource.org/display/Hifaces20/Hifaces20+Testing+package+-+testing%2C+tracing+and+debugging+web+applications+with+Jetty

1 doesn't resolve this issue. WebApplicationContext stays null
2 states that support for WebApplicationContext will be available in spring 3.2
3. I don't understand this. Where do I get the testApplicationContext and the getServletContext() from?
4. I do not want to go this way as this is completely blackbox testing.
5. I'm currently looking at 5. But this requires starting up a servlet container. Is there no other alternative?

I will appreciate any help you can provide.

Thanks PixalSoft

@Ted Young SO didn't allow me to finish what I was saying.With loader=MockWebApplicationContextLoader,isn't it supposed to be available as the default contextloader exactly as the Spring ContextLoader behaves when the webapp is initialized by a servletcontainer?Is there something special I need to do get a handle on the MockWebApplicationContextLoader?Injecting the config object works for singleton objects. But all can't be singleton. Passing a config object in every constructor sounds too tedious. For now, I have created a class which has a static config object, autowired via a setter method. I will take a look at ApplicationContextAware.Many thx

like image 750
user1373927 Avatar asked May 04 '12 01:05

user1373927


3 Answers

You have to manually add the WebApplication context to ContextLoderListner. This will work.

@ContextConfiguration(locations = "classpath:module-test-beans.xml")
@WebAppConfiguration
public class SampleTest extends AbstractTestNGSpringContextTests {

    @Autowired
    private WebApplicationContext wac;

    @BeforeClass
    public void setUp() throws ServletException {
        MockServletContext sc = new MockServletContext("");
        ServletContextListener listener = new ContextLoaderListener(wac);
        ServletContextEvent event = new ServletContextEvent(sc);
        listener.contextInitialized(event);
    }

    @Test
    public void testMe() {
        Assert.assertFalse(ContextLoader.getCurrentWebApplicationContext() == null);
    }
}
like image 109
Shiran Avatar answered Oct 27 '22 06:10

Shiran


Add the following code at the beginning of your junit test:

MockServletContext sc = new MockServletContext("");
sc.addInitParameter(ContextLoader.CONFIG_LOCATION_PARAM,
        "/applicationContext-test.xml"); // <== Customize with your paths
ServletContextListener listener = new ContextLoaderListener();
ServletContextEvent event = new ServletContextEvent(sc);
listener.contextInitialized(event);

If you need to add more than one xml for the context path just put them in the same string separated with spaces, like this:

sc.addInitParameter(ContextLoader.CONFIG_LOCATION_PARAM,
        "/applicationContext-test.xml /applicationContext-other.xml");
like image 24
qwertzguy Avatar answered Oct 27 '22 04:10

qwertzguy


The reason why ContextLoader.getCurrentWebApplicationContext is returning null is because, when you use my MockWebApplicationContextLoader, you are neither using a web application context nor that particular ContextLoader implementation.

Since your repository is managed by Spring, why do not you simply inject the config object into the repository? Injecting the config object is the most appropriate way to get access to it. You can then initialize your namespace property in a method annotated with @PostConstruct.

Alternatively, your DOA could implement ApplicationContextAware to receive a copy of the application context during construction.

like image 42
Ted Young Avatar answered Oct 27 '22 06:10

Ted Young