Erando
Erando

Reputation: 899

Spring MVC: ServletContext in JUnit Test?

As I'm new to Spring MVC please help me diminish my confusion.

I've got this Service and need to write a unit test for it:

public class SendEmailServiceImpl implements SendEmailService {

private final static Logger logger = LoggerFactory.getLogger(SendEmailServiceImpl.class);

@Autowired
private JavaMailSender mailSender;

public void sendEmail(String id) {

    logger.info("Preparing the mail");

    String mailFrom = Config.getProperty("email.from");
    ...
    }
}

So this sendEmail-Method makes use of the static method Config.getProperty. The Config class gets initialized in the Servlet init()-method:

import java.io.File;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServlet;

public class ConfigLoader extends HttpServlet {

    private static final long serialVersionUID = 923456796732565609L;

    public void init() {

            String configPath = getServletContext().getInitParameter("ConfigPath");

            Config.init(configPath);
            System.setProperty("org.owasp.esapi.resources", configPath + "/conf");

        cleanupDirectories(getServletContext());

    }
}

So in the end I for the test case for my sendEmail() method I need to have access to the servlet context. Giving the official docs I was under the impression that the @ContextConfiguration and the @WebAppConfiguration annotations would solve my problem. So my unit tests looks like:

import javax.servlet.ServletContext;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;

import SendEmailService;

@WebAppConfiguration("file:application/webapp")
@ContextConfiguration("file:application/webapp/WEB-INF/dispatcher-servlet.xml")
@RunWith(SpringJUnit4ClassRunner.class)
public class SendEmailServiceImplTest {

    @Autowired
    private SendEmailService sendEmailBean;

    @Autowired
    ServletContext context;

    @Test
    public void sendMail() throws Exception {
        sendEmailBean.sendEmail("b884d8eba6b2438e8e3ee37a69229c98");
    }
}

But unfortunately Config.init(configPath); has never been called which means the ServletContext hasn't been loaded.

What could I be missing here...?

Upvotes: 1

Views: 4312

Answers (1)

Testo Testini
Testo Testini

Reputation: 2240

A service should not depend on the web layer, you should have two application contexts: one for services and one for the web and use only that of services for tests (of services). You have a dependency that should not be there, the service code works because you get the property at the moment of sending but at initialization time the service has no access to that property because it still has to be configured by the init-servlet.

Instead than initializing from a Servlet you should create a bean in the services application context, there instead of using init-param you can use bean properties for configuration. An other option is to use the service class itself to hold the property and do the initial configuration.

Upvotes: 2

Related Questions