3

The aim is to, for each unit test, systematically start a tomcat 7 server, load the spring application (eventually drop / create a schema & init its data in an database) perform unit tests and stop the http server.
It is quite easy to found sample in order to do that with jetty embedded server

I DONT found the right way to configure the embedded tomcat 7 server in order to load spring context
Can you please help me ??

project structure is a standard maven webApp project named "myApp"

src
 +-main
  +-java
  +-webapp
   +-static
   +-WEB-INF
    +-web.xml
    +-applicationcontext.xml
target
 +-myApp
  +-webapp
   +-static
   +-WEB-INF
    +-classes

the abstract unit test:

import org.junit.After;
import org.junit.Before;
import org.junit.runner.RunWith;
import org.apache.catalina.Context;
import org.apache.catalina.core.AprLifecycleListener;
import org.apache.catalina.core.StandardServer;
import org.apache.catalina.startup.Tomcat;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.WebResource;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"applicationContext.xml"})
public abstract class AbstractMainHTTPTestCase
{

   private int                 PORT;
   private Tomcat              tomcat;
   private String              appBase;
   private String              contextPath;
   private String              hostname;
   private String              baseDir;
   public Client               client;
   public WebResource          webResource;
   public String               response;


   @Before
   public final void setUp() throws Exception
   {
      this.PORT = 8081;
      this.appBase = "src/main/webapp";
      this.contextPath = "";
      this.baseDir = ".";
      this.hostname = "localhost";

      this.tomcat = new Tomcat();
      this.tomcat.setPort(this.PORT);

      this.tomcat.setBaseDir(this.baseDir);
      this.tomcat.getHost().setAppBase(this.appBase);
      this.tomcat.setHostname(this.hostname);
      Context ctx = this.tomcat.addWebapp(this.contextPath, this.appBase);

      File contextFile = new File(this.appBase + "/WEB-INF/web.xml");
      ctx.setConfigFile(contextFile.toURI().toURL());

      this.tomcat.start();
      this.tomcat.getServer().await();
   }

   @After
   public final void tearDown() throws Exception
   {
      this.tomcat.stop();
   }
}

and a typical test class for testing an URL:

import static org.junit.Assert.assertNotNull;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.sproutcore.sample.todos.AbstractMainHTTPTestCase;

public class MainControllerTest extends AbstractMainHTTPTestCase
{

   private static final Logger LOG = LoggerFactory.getLogger(MainControllerTest.class);

   @Test
   public void staticTest() throws Exception
   {
      LOG.debug("HTTP TEST: staticTest");
      this.response = this.webResource.path("/static/test.txt").get(String.class);
      LOG.debug("staticTest response: {}", this.response);
      assertNotNull("Static test shall be not null", this.response);
   }

}

Static folder is configured in applicationcontext.xml:

<!-- Handles HTTP GET requests for /static/** -->
<mvc:resources mapping="/static/**" location="/static/" />


This way of working force / allow people to code first unit tests & create data unit test, then to code application functions. Tests are automatically performed when packaging application with maven. You can generate tests reports too... Best practices...

starblue
  • 55,348
  • 14
  • 97
  • 151
nano31
  • 31
  • 1
  • 3

1 Answers1

1

can you be a little more specific about what does not work with this?

i think it could be 2 things.

1st. this.tomcat.getServer().await();

blocks the thread so no test-methods get invoked, i was browsing for the same thing and if you have your code from http://www.copperykeenclaws.com/embedding-tomcat-7/, this only makes sense in a main-method

2nd. it's maybe a problem with

@ContextConfiguration(locations = {"applicationContext.xml"})

this annotation lets the JUnit-Runner load the spring configuration. so i can imagine that there could be a conflict when the tomcat loads the spring-configuration again.

Christian Specht
  • 35,843
  • 15
  • 128
  • 182
cproinger
  • 2,258
  • 1
  • 17
  • 33
  • well, thank you for your response. I already take a look at this publication (and my sample is inspired from ti), and I already use the "await" command as you can see above. You can find here [link](https://github.com/sorriso/TodoSRV) an application sample using an embedded version of jetty to test RESTful services: the spring context is used to setup the database, then jetty is launch (from web.xml & context.xml files) and test are runned. Today I am still not able to do the same thing with an embedded version of tomcat. Do you know how to do that ? – nano31 Nov 07 '11 at 19:31