0

I am trying to implement integration tests for my Tomcat application, but my issue is that the application is launched separately from the tests so the tests cannot access the application context and neither the database.

My idea is running the tests "within" the running application, so I can @Autowire EntityManager and check for instance the state of the database during testing or even create database entities for testing.

My only idea of doing this is to actually run the application programmatically from the tests as ClassPathXmlApplicationContext("applicationContext.xml") and the access the Context. This would work, but it would be very hard for debugging as we wouldn't be able to use Hotswapping during the testing. Also I guess the server would be stopped as soon as the tests would end. I guess that is not the best and correct solution.

EDIT:

My question was probably unclear, so I will try to clarify.

I have a Tomcat application with Spring and Hibernate. The Spring beans and Hibernate database connection is initialised when the Tomcat application is started. The issue is how to run the tests of the active Spring beans from methods annotated with @Test in src/test/java which are started separately.

Consider this class:

@Component class MyRepository { @Autowired EntityManager em; @Transactional public void myMethod(MyEntity entity) { // do some job with entity ... em.flush(); } } 

This class will be initialised with Tomcat as a MyRepository bean.

To test it, I cannot just call new MyRepository().myMethod(...) - I need to access the bean. The issue is accessing the bean from the @Test method:

@Test void testMyRepository() { Item item = ... // then use the repository to handle the entity context.getBean(MyRepository.class).myMethod(item); // then assert the state of the database context.getBean(EntityManager.class).find(Item.class, ...) ... } 

I can probably get the context in the initialisation of the tests with

ApplicationContext context = ClassPathXmlApplicationContext("applicationContext.xml"); 

But it would mean launching the whole application each time the tests are started. The better solution would be if the application could run separately from the tests.

Hope my problem is more clear now.

3
  • It's a bit hard to know what you're actually asking here. Your main concern seems to be to be able to open a debugging session to a server which is basically booted manually? Commented Jan 25, 2018 at 16:04
  • 1
    Vojtěch, do I understand it correctly - you cannot use the standard SpringRunner and start the Spring application context from your test. You tests should connect to an external instance of you application? Does your application have some (REST) API? Do you want to test just individual Spring beans or the application as a whole (from its API down to the DB layer)? Can you explain reasons? Commented Jan 25, 2018 at 21:09
  • The application is connected to SQL database and potentionally other sources (like testing instance of Elastic search). It can be launched by somethinkg like SpringRunner, my problem is that I don't know what would be the correct way to do it. And also – launching the app before every single test would be time consuming as it takes roughly 30-60s to start the app. The best would be if the tests could run independantly. The App has an API, but I would like to test deeper parts of the system, not only the API responses. Commented Jan 25, 2018 at 21:21

2 Answers 2

2

I would suggest you to use the SpringRunner to start the Spring application context and perform your tests on that running instance. You can customize the context the way it doesn't contain parts you don't want to tests and you can create mocks for components that require some external resources (REST clients and such). Take a look at the Spring docs or Spring Boot docs.

If multiple tests use the same Spring context configuration, the context is started just once and reused. So it's good to have it's configuration in a parent class of your tests. You can autowire any Spring bean into your test and test it.

You can use an in-memory database (such as H2) instead of a production one, so your tests are not dependent on an external infrastructure. To initialize the database, use tools like Flyway or Liquibase. To clear the database before each test, you can use the @Sql annotation.

You can find many examples of projects with such tests, for example my own demo.

If you want to test an external system, I would suggest something like JMeter.

Sign up to request clarification or add additional context in comments.

1 Comment

SpringRunner was the way to go. Thanks
0

Unfortunately you cant mirror your classes and use them in your tests. Thats a big disadvantage of web services. They always depend on user / machine interaction. With a lot of effort you can extract the functionality of the essential classes or methods and construct test scenarios etc. with jUnit. The Overview of your possibilities:

  • special drivers and placeholders
  • you can use a logger with detailed log-level and file output. Then you created scenarios with the expected result and compare it with your log files.

  • Capture replay tools. They record your exection and replay them for monitoring.

  • I can also recommend using Selenium for the frontend tests.

Hope it helped.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.