Spring Boot IT test after Deploy - java

I have Spring Boot Integration tests (IT) that connect to a real DB or to a real 3rd parties. I use them during development but I find them quite usefull to check the real behaviour of the application therefore I would like to run them during CI process. The goal is to run them on the environment on which the application is deployed and not on CI machine where Jenkins is running. Is there a way how to achieve this? I know I can use for example SOAP UI maven plugin and execute tests against REST endpoints, but I would prefer to use Spring Boot IT tests already written.
Many thanks

Running tests against your production database is a really bad idea. Please please please reconsider. It is better to have your test database updated to be more like production than to run your tests on production data.
That being said, you can point your database configuration to your production machine via the application.properties file (mongo example):
spring.data.mongodb.uri=mongodb://user:pass#production.myhost.com:27017/mydb
I'm guessing that it defaults to localhost:27017. In your test/resources folder you can setup a differing application.properties. Check out the spring-boot externalized properties details.

Related

What is the difference between Profiles via Spring or via a build tool like Maven/Gradle

We are currently developing a Spring Boot based application and we have a QA and a Prod environment to deploy.
I suggested that having different app properties file for different environments and then using -Dspring.profiles.active in a Docker compose file would be a good solution for profiling.
But, my colleague says that having a build tool based profiling would be a better idea. Something like this - https://mkyong.com/maven/maven-profiles-example/
Please help me understand the advantages and disadvantages between these two ways as I am not finding sufficient reading materials online.
With Mvn/Gradle profiles, the profile is selected at build time. So you will need to rebuild your project for Prod after it's accepted on QA.
With Spring, the profile is selected at runtime. You can deploy the same WAR file or Docker image on QA or on Prod, but you only need to change the runtime profile, e.g. via the command line -Dspring.profiles.active=... or via an environment variable SPRING_PROFILES_ACTIVE=..., and Spring will select either application-qa.properties or application-prod.properties during startup.
Having the same Docker image on Prod or QA is definitely better, I think. The downside of using Spring profiles that you include the property sets for both QA and Prod inside the image, and when you want to change either one, you will have to rebuild the whole Docker image.
A third option is not to use profiles at all, but externalize all properties that are not the same for QA or Prod. For example, set spring.datasource.url, username, password, etc, via a deploy descriptor rather than include it in your docker image. This way, you can reuse the same Docker image for any environment, and reconfigure it on the fly. Additionally, you can keep production passwords secret from developers if you want.
What #JArgente suggest goes even a step further: read the properties from an external service at startup time. But that may be overkill, if you can do it via Kubernetes environment variables.
To compare Spring and Mvn/Gradle is to compare 2 tools designed for different things.
Both however, allow you to feed configuration through different mechanics. Spring profiles are intended to be used for deploying applications in different environments, so in terms of use-case and intended use, what you described fits in to this.
(Ref: https://docs.spring.io/spring-boot/docs/1.2.0.M1/reference/html/boot-features-profiles.html )
Here's a couple of advantages of using Spring profiles over a build tool's config
I thought of:
Can switch profile without rebuilding the application
Can debug the application itself rather than looking at the build config, which should be easier
I think the best approach to change configuration based on environment is to use an external config server where the service will connect at startup and fetch the configuration that applies to the environment where the app is deploying.
For example, you can use spring-cloud-config server and create different configuration files for each environment and when the service deploys, use spring profiles to know what is the environment in which the application is being deployed and get the correct configuration:
https://cloud.spring.io/spring-cloud-config/reference/html/

Spring Boot test profile

I want to run UAT tests using Spring Boot. I want to run them on multiple configurations in parallel.
I will start by saying that I'm not sure if it's a good practice to run mvn test on the same project in parallel. But let's pretend I'll do that.
The suggestions I find on the internet for testing different configurations are:
either have different profiles and put this in the base application.yml : spring.profiles.active=profilex
either use environment variables instead of profiles
Both will not work with running in parallel: application.yml can't have different values at the same time, the same with environment variables.
Is there any kind of way to specify the profile with command line arguments, something like mvn test -DprofilesActive=profilex ? Or any other way?
EDIT - concrete example:
I have a REST service deployed on 2 servers.
I have a separate project for testing the REST service using Cucumber (so JUnit tests). This is a Spring Boot project. It takes the URL of the server where the REST service is deployed from application.yml (at the moment).
I want to run this test project in parallel twice , for each deployed REST service, meaning with the 1st URL and the 2nd URL.
I run it using mvn test.

How to verify that a spring-boot web server is running

I am writing an integration test for a spring-boot web server
I want to use junit-jupiter (junit5) to check if the server is running using Assumptions.assumeTrue so that the test do not fail if the server is not running...
There seems not to be any API support for such operation, but can it be achieved in some other way? Pinging the server?
You could make use of the actuator module in spring boot. It will provide you with a health check URL and you could make a call to this URL and verify that it returns healthy.
Now that that is out of the way, if you need the server to be running while running your tests, you should probably be using the spring boot test runner, instead of using the JUnit runner. In this case you could still mock some of your spring beans and achieve the same kind of test, but with a spring context running alongside your tests. The downside of this is the overhead of needing to spin up the spring context before running tests, but if you need to use the actual web server, then this is what you should be doing.

How to deploy spring boot web application with configurable properties

After researching i learned that the common way to deploy spring boot web applications is as a war file.However,i have a project i made for a company,now i need to send them the project to try it out and they need to be able to configure the application.properties or to be specific the database location and credentials.so my question is do i need to deploy the project in a different way or is there a way to make the war file application properties modifiable later ?
Did you consider Spring Cloud Config Server
https://cloud.spring.io/spring-cloud-config/multi/multi__spring_cloud_config_server.html.
This is the most elegant way to configure and externalize your properties. If not I would strongly suggest incorporating that component. Plug the config server with your spring boot app without much coding and your application will be much more manageable and extensible.
Spring Boot applications are actually typically packaged as Uber jars with Tomcat embedded. You can accomplish this using spring-boot maven plugin or a similar gradle plugin if need be.
Once in this state the jar can be started normally and you can override configuration properties when invoking it.
java $JAVA_OPTS -Dspring.service.name=my-service -jar /my-service.jar
EDIT: This is not the only way you can solve this problem, and #piy26's answer is an excellent solution for injecting external configuration into an enterprise ready spring boot application. However for the case that your are describing you would need the company to set up there own configuration server, and whats more they will still have to override the configuration server location property so the application will pull properties from their config-server. For your example it seems you need the simplest way to override application properties within the jar.

How to run multiple Spring Boot applications easily on Production

I am trying to figure out an easy way to manage many Spring Boot applications on my Production server. Right now I have many fat jars running on different folders where each one has its your own script to start/stop the application and there's an external folder for the configurations (logback, properties, xml). For record those configurations are loaded by command line -Dloader.path to Spring Boot execution.
So how can I avoid conflicts for the same http/https port already running on Production? Does exist any kind of application manager where system administrators could control it? One solution I found was to virtualize Spring Boot applications with Docker, but my environment is Unix Solaris.
Is there any java solution for this scenario?
You can have a look at Spring Cloud which will give you better control and management when running multiple boot applications. All components of Spring Cloud
might not be useful to you, but few of them will help in port resolution, service rerouting and property maintenance. Along with the above you can also try SBA.
Along with the above you can also try Nginx for UI load balancing and reverse proxy.

Categories