End to end test across multi Spring Boot applications - spring-boot

Currently in our project, we are using Spring Integration to integrate many service and some protocol related endpoints.
The project is a multi Spring Boot applications, more than one executable jars will be deployed in production.
The question is:
How to run an end to end test which needs to run cross some of these applications, I have to run the one by one manually? In before none-Spring-Boot applications, I can use Maven tomcat7 plugin to complete this work(deploy the wars into an embedded tomcat and run it in pre-integration-test phase), now how to start up all related applications before I run my test. Assume I do not use Docker/Vagrant now.
Similar question found on stackoverflow, End to end integration test for multiple spring boot applications under Maven
How to run the end2end test automatically?
In an Spring Integration test, sometime I have to mock a http endpoint, so I wrote a simple Controller in test package to archive this purpose, but I want to run it at a different port, which make it more like an outside resource. How to run different #SpringBootApplicaiton classes at varied ports at the same time in the test for this purpose?
I am using the latest Maven, Java 8, Spring Boot 1.3.1.RELEASE.

Actually, Spring Boot comes with the embedded Servlet Container support. One of them is exactly Tomcat. The default on for the org.springframework.boot:spring-boot-starter-web.
With the org.springframework.boot:spring-boot-starter-test and its #SpringApplicationConfiguration and #WebIntegrationTest you can achieve your requirements, even with the random port.
Please, refer to the Spring Boot Reference Manual for more information:
To change the port you can add environment properties to #WebIntegrationTest as colon- or equals-separated name-value pairs, e.g. #WebIntegrationTest("server.port:9000"). Additionally you can set the server.port and management.port properties to 0 in order to run your integration tests using random ports.
With that your #SpringBootApplicaiton will be deployed to that embedded Tomcat and your test can get access to the ran services/controllers.
Note: it doesn't matter if your Spring Boot application has Spring Integration facilities. The behavior is the same: embedded Servlet Container and integration tests against #Value("${local.server.port}").

Related

Does every spring boot application create a tomcat container to be able to run?

For example,
I understand adding specific dependencies like spring-boot-starter-web that contains tomcat as transitive dependency triggers the spring framework to initialize tomcat container but I want to know if we say a spring-boot application is running, does it imply always that tomcat is also running?
I want to know if we say a spring-boot application is running, does it imply always that tomcat is also running?
No, it doesn't.
Spring boot can be used for both web applications and non-web applications.
For web applications you can use tomcat/jetty/undertow/netty for example, its up to you to chose what works for you the best.
If you don't want to run an embedded version of the web server you can opt for creating a WAR file and place it into the web server prepared in-advance.
If you don't want to run web application at all (something that is built around "Request - Response" way of work in the most broad sense) - you can create a "CommandLineRunner" - in this case you don't need to depend on neither web-mvc nor webflux. For more information about Command Line Runners read here for example
You can have an embedded server in your JAR that is able to be run on its own. By default it is Tomcat but you can change this to others, like Jetty. Additional details:
https://docs.spring.io/spring-boot/docs/2.0.6.RELEASE/reference/html/howto-embedded-web-servers.html
If you don't want to have an embedded server and you want to deploy your application you can also create WAR files instead of JAR files. Additional details:
https://www.baeldung.com/spring-boot-no-web-server
https://spring.io/guides/gs/convert-jar-to-war/

Run external spring boot application as part of an integration test

Is it possible to run an external Spring boot application from an integration test? The basic idea is that I have a mock service that was developed for use in end to end testing and would like to be able to have the e2e integration test take care of starting up the service and shutting it down as part of the test.
I recommend you take a look at docker and the fabric8 maven plugin. This allows you to build container images that contain your application, start and stop instances of those containers as part of your integration test phases.

Spring application context in multiple tomcats

If there are multiple web applications in different tomcats, how to configure same application context for all the tomcats
I am not sure if i understand the question correctly. I guess you misunderstand some concepts. First, what is your package; is it war or jar. Do you use Spring MVC or Spring Boot (If you are new i suggest you to use Spring Boot). If you are using Spring MVC you are required to deploy your war to a servlet container like Tomcat. And if you want to deploy your applications to multiple tomcats, it is possible of course. However each application run on their own application context. These application contexts will have same beans and will be on same state when they are firstly initialized. As far as i know it is not possible to share one application context over multiple spring mvc applications and i think it doesn't make sense.
If you are using Spring Boot, your application will run on JVM with an embedded servlet container. In this case, your application is packaged in a JAR file with servlet container and you are not required to deploy the application. When you run the application both servlet container and your application context is initialized. In this situation, you can run multiple applications and as i said before these applications will have different application contexts.

Deploy spring boot applications

I know spring boot applications can be deployed to production environments as war files. But what is the typical way of deploying spring boot applications? Does it only require a jvm, not a container?
The Spring Boot Project Page states that Spring Boot makes it easy to create stand-alone, production-grade Spring based Applications that you can "just run".
Means by default, the Spring Boot maven or gradle plugin builds self-contained executable jars, that contain all dependencies and an embedded webserver, e.g. tomcat or jetty. The Spring Boot Getting Started doc gives you an introduction to that. Using this approach you just need a JVM to run your application. But you can also configure it to create war files if this is a better fit to your production environment.
Does it only require a jvm, not a container?
It can run anywhere Java is setup.
Spring Boot's use of embedded containers and why Spring chose to go the container-less route. Many of their main driving forces were ease of use while testing and debugging, and being able to deploy Spring-based Java applications to the cloud, or any other environment.
Rest can be found out in attached image.
Spring boot applications if they are serving web requests do require a container. You can either deploy them as a war inside a container such as tomcat/jetty. Or you can deploy them with embedded container, tomcat.

Rollback Integration Test which uses cucumber and tests the application on embedded tomcat via maven

I am trying to set up an integration test framework for my spring project using cucumber framework and selenium for UI automation.
What I have done till now is
Use tomcat7 plugin for maven and deploy my war file to this embedded tomcat
Use the cucumber feature file to specify any test cases, be it a rest service or for the UI automation
We need to use our existing development DB for test purposes
I will hit the app url for the application running on the embedded tomcat.
What I am unable to find out is, can we rollback a transaction automatically after the test is done?
I am able to rollback transactions from cucumber/junit that were directly using my DAO as the DB connection was initiated from the same spring context.
But when the invocations are made using this model, I am unable to find any idea to rollback the transactions after the tests are done.
Can you think of achieving your integration testing in terms of Spring profile? You can create a spring profile for integration test and use it as environment variable or using annotations to specify rollback for transaction.
Take a look at following references to get an idea:
Spring integration tests with profile
https://spring.io/blog/2011/06/21/spring-3-1-m2-testing-with-configuration-classes-and-profiles

Resources