2

I'm working on an application that needs to run up a TCP server as one of the first things it does. This is currently initiated via a Spring config class:

@PostConstruct
public void initTCPServer() {
    // Gets the port number and other values from the database...
    // Note: This uses dependency injection of the Data Access Objects (DAOs).
}

It works fine when using an existing pre-populated database but I'm running into problems when trying to write an integration test: The data needs to be pre-populated but the @PostConstruct is firing before the data population if it is in a JUnit @Before method and similarly when using SpringJUnit4ClassRunner's @TestExecutionListeners.

The only solution I can think of now is to initialise data in a test config class with a @PostConstruct and ensure this is loaded first - but this seems a bit dirty. EDIT: Just tried and this failed with a BeanCurrentlyInCreationException - looks like dependency injection of the EntityManagerFactory hadn't finished.

Is there a more elegant way (e.g. should I be running up the TCP server somewhere else, i.e. not managed by Spring)?

Steve Chambers
  • 37,270
  • 24
  • 156
  • 208
  • How are you populating your data in you JUnit test ? – Alexandre Jacob Sep 25 '15 at 12:40
  • Via Data Access Objects (DAOs) that sit a layer above Hibernate for simple CRUD operations and are injected into a transactional data populator. – Steve Chambers Sep 25 '15 at 12:43
  • You could use a different DataSource configuration for testing, populating it directly in the bean definition. For this purpose you could also have a look to Spring Profiles: [1](http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#beans-definition-profiles-java) [2](http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#testcontext-ctx-management-env-profiles) – Francesco Pitzalis Sep 25 '15 at 13:22
  • Is it a prerequisite for you to use DAO's or could you just load SQL scripts ? – Alexandre Jacob Sep 25 '15 at 13:23
  • We are using Spring Profiles and think my preferred solution is to have a separate bean that excluded by the profile and then loaded manually at the start of the test. Not ideal as it doesn't exactly simulate the order in which events will really occur but it's the best I've got so far. – Steve Chambers Sep 25 '15 at 13:31
  • Definitely prefer DAOs to SQL scripts. SQL scripts are brittle to changes being made to the entities and bypass JSR-303 validation being performed by hibernate-validator. Scripting would also require Hibernate managed concepts such as versioning (@Version) and inheritance to be done manually. – Steve Chambers Sep 25 '15 at 13:33
  • 1
    May be turn your bean to a `lazy` bean so the `@PostConstruct` get called later on, after initialization of your data. To do so you'll have to ensure that your `applicationContext` doesn't need to initialize your bean itself before running your DAO calls. – Alexandre Jacob Sep 25 '15 at 14:54
  • 1
    Don't tie the lookup of the properties directly to the database. Instead of that use the `Environment` abstraction, at run time load the properties from the database and add them as `PropertySource` to the `Environment` for your test simply use a property file. That way you don't need a prepopulated database. – M. Deinum Sep 25 '15 at 19:11
  • 2
    Remove the need for a `@PostConstruct` and make the creation of the server lazy. Doing it in a method annotated with `@Before` is always going to be too late and thus will always fail. If this is only properties I would suggest simply adding a sql script and in your test configuration add a `jdbc:initializer` to it which would execute the sql at startup. You could also add a cleanup script to remove the values afterwards. – M. Deinum Sep 25 '15 at 19:15

0 Answers0