0

We are using cucumber-jvm to write an integration test layer in our application. One of the challenges we are finding is managing the database between the tests and the web application.

A typical scenario is that we want to persist some entities in a Given step of a scenario, then perform some actions on the user interface that may, in turn, persoist more entities. At the end, we want to clean the database. Because the cucumber-jvm tests are in one jvm and the web application is running in another jvm we cannot share a transaction (at least in a way of which I am aware) so the database must be cleaned manually.

My initial thought was to use an Embedded Tomcat server running off of an embedded in-memory database (HSQLDB) in the same JVM as the cucumber-jvm test. This way we might be able to share a single spring container, and by extension a single transaction, from which all objects could be retrieved.

During my initial tests it looks like Spring gets loaded and configured twice: once when the test starts and the cucumber.xml is read, and a second time when the embedded tomcat starts and the web application reads its applicationContext.xml. These appear to be in two completely separate containers because if I try to resolve an object in one container that is specified in the other container then it doesn't resolve. If I duplicate my configuration then I get errors about duplicate beans with the same id.

Is there a way that I can tell Spring to use the same container for both my test application and the embedded tomcat?

I'm using Spring 3.2.2.GA and Embedded Tomcat 7.0.39 (latest versions of both libraries).

Am I crazy? Do I need to provide more technical details? Apologies if I use some incorrect terminology.

Thanks

p.s. If my problem seems familiar to you and you can suggest an alternative solution to the one I am trying, please let me know!

Jeffrey Cameron
  • 9,975
  • 10
  • 45
  • 77

2 Answers2

1

Jeff,

It is normal that spring is loaded twice. There are two places where two spring contexts are created:

  1. In the servlet container listener org.springframework.web.context.ContextLoaderListener that is configured in web.xml. This one reads its configuration from the file set by the context-param contextConfigLocation.
  2. In the implementation of ObjectFactory provided by cucumber-spring plugin cucumber.runtime.java.spring.SpringFactory. This one reads its configuration from cucumber.xml.

The two spring contexts are totally different and their instances are kept in two different places. As a servlet context attribute for the former and kept by the JavaBackend for the latter.

When starting the embedded tomcat, it is possible to get access to the servlet context and thus set ourself the spring context used bt tomcat with the one from cucumber. But, spring has a special class called WebApplicationContext for context used in a servlet container. The cucumber SpringFactory on other hand creates its context through ClassPathXmlApplicationContext. So unless there is a way to specify the type of application context from the xml config, we will have to provide an ObjectFactory that shoots a WebApplicationContext.

Thierry
  • 11
  • 1
  • I did find an answer that approximates what we need. You can set a parent context for the WebApplicationContext, this could be the ClassPathXmlApplicationContext. See this answer: http://stackoverflow.com/questions/14608373/sharing-application-context-between-javase-and-web-application – Jeffrey Cameron Apr 13 '13 at 11:00
  • Another follow up question: if we could use the parent context of cucumber-spring in the web application then we would want to define all of our services, data sources, transaction, etc. in the cucumber.xml for the tests, but define them from web.xml when starting ther server normally. How could we do this? – Jeffrey Cameron Apr 13 '13 at 11:16
0

What we can do is to have two web.xml. One for the normal and one for the test. For the test, we use our version of the ContexLoader listener.

  • I'm a step ahead of you. See this question http://stackoverflow.com/q/15988578/61344 – Jeffrey Cameron Apr 14 '13 at 10:38
  • But what if we address the web.xml issue at the build level? Instead of loading tomcat from src/webapp we can use target/webapp in which the correct web.xml has been copied over. – Thierry Apr 14 '13 at 20:53
  • Thatès an interesting idea! I actually got it working today though. I just configured the web.xml programmatically. I can show you tomorrow. It shouldn't be too hard to take the packaged solution from the sandbox and apply it to the main codebase. – Jeffrey Cameron Apr 15 '13 at 00:23