I'm trying to write unit tests on a DAO class which uses Spring-Mybatis. I'm running the unit test with maven without running the web application. The error that I'm getting is java.lang.NullPointerException at line WebApplicationContext ctx = ContextLoader.getCurrentWebApplicationContext(); (Please see below for code snippet). However, I can successfully run the unit test if I call the LocationDAOService class directly in the test class.
Does anyone know a way to unit test the class that uses the WebApplicationContext/ContextLoader.getCurrentWebApplicationContext() outside the web containter?
Why not just @Autowire the LocationDAOService. Assuming the LocationDaoService is an interface you can mock it if you need to. This is not really a use case where you should be using WebApplicationContext .
Autowire wont work in this case because class LocationDAOImpl is legacy code and is not a bean(not part of Spring). This is why the I'm using WebApplicationContext to get LocationDAOService bean. Works perfect. But not so well with unit testing. Does anyone know a way to write a unit test that tests a class utilizing ContextLoader.getCurrentWebApplicationContext()?
I would recommend re-factoring that an making it a bean, it really should be a bean for more reasons than 1.
Anyway if you are going to go down this other path they have made major improvements in Spring 3.2 as far as testing goes. One thing the have added is the test-mvc package. To use this you would have to grab that dependency out of the Spring repos as it is not available in Maven central yet. But you can read about it here.
I talked a little about some of its features in the link below. I would follow the 2 links above though as there have been additional improvements and changes made since I posted and there are also now official demos projects that exist that were not there when I posted, but you can have a look to get an idea.
I actually have tried to make the class I'm testing a spring bean, however, this approach wasn't working consistently. For some beans, it failed to get the applicationcontext. I've also tried to implement applicationcontextaware to get the applicationcontext. However from reading materials online, a web application should stick with using webapplicationcontext and not applicatoncontext. Not to sure why, but it has to do with something about the default bean scope for application context is 'singleton' compared to 'request' for webapplicationcontext.
Brian Wheeler wrote:
For some beans, it failed to get the applicationcontext. I've also tried to implement applicationcontextaware to get the applicationcontext.
I guess I fail to see why a repository/DAO bean would need access to the application context. Maybe if you can explain that to me I could help more. In almost all cases your Spring beans should be unaware of any Spring stuff including the Context.
Code like context.getBean is many times an indicator that your are doing something wrong. One of the primary principals of Spring is Dependency Injection which works in just the opposite way, you don't look them up but rather the framework injects them.
I'm using Spring/Mybatis for the application's data access layer. There is a spring bean service class that basically injects a mapper that does all the SQL calls. The class I'm trying to write unit test for is a legacy code that was originally implemented using JDBC. I modified this legacy code to utilize Spring/Mybatis. And the only way I got it to work was to get the applicationcontext so that I can get the service beans to make the database calls.
I've tried to make this legacy code a bean by adding @Component/@Named so that I can inject the service class, however, this didn't work for me.
But looking at their page it looks like you should be able to inject your mapper into your Spring managed service bean... Is that where it is failing? Assuming the service itself is a spring bean there should not be a problem. Often times when your dependencies are not being injected it is when the class is created with the new operator. In this case it will not be a Spring managed bean. Maybe double check this is not the case for you.
The service Spring managed service bean works fine and injects mappers successfully, no problem there. The part where it's failing is when I try to register legacy classes as Spring beans. These legacy classes are created with the new operator, which could explain the problem. For this reason, I am using webapplicationcontext to get access to the Spring/Mybatis service beans.