SpringBoot: how to run tests twice, with two different config files - spring

I am writing a SpringBoot application using a JMS MOM. My application supports two kinds of JMS: EMS and AMQ
My application has many Junit Tests. Of course, whether I use EMS or AMQ the tests are exactly the same and the expected results are also exactly the same. The only difference is the configuration file used.
#RunWith(SpringRunner.class)
#TestPropertySource(locations="classpath:application.yaml")
#ContextConfiguration(initializers = ConfigFileApplicationContextInitializer.class)
public class MyTest {
#SpringBootApplication
#ComponentScan("com.mytest")
static class Application {
}
#Test
public void test() {
...
}
}
What I would like to be able to do is to run my tests twice, one time with an EMS config and one time with and AMQ config: How should I do?
FYI, I am using Maven to build my application. A solution based on a maven trick would be perfectly acceptable for me
Thank you for help

It sounds like a task for a building tool that you using.
For example, for Maven you can write specific test tasks with different active profiles, something like this:
mvn clean test -Dspring.profiles.active=kafka
mvn clean test -Dspring.profiles.active=rabbitmq
mvn clean test -Dspring.profiles.active=activemq
and collect necessary properties in files: application-{profile}.properties
This articles can help you:
how to bind a property file to a current active profile: spring-boot-profile-based-properties
mvn profiles:
introduction-to-profiles
mvn different environments:
building-for-different-environments

Related

Maven Tests not Running in sequential Order

I'm using a TestNG framework for my automation project.
While running from command line i'm giving the following command.
mvn clean test -Dtest=Login,OpenImage,Logout
By running the above command it the order of execution was Login->Logout->OpenImage (may be in alphabetical order).
Can anyone help me how to run tests in the given order.
Note: As per my requirement I need to run my tests in the above way it self.
If it was through testNG.xml file then i guess preserve-order will work.
can anyone help me on this.....!!!!!
Thank you in advance..
First why do you need to run tests in a particula order because units should never rely on a particular order. But your question looks like more an integration tests.
If you need to run in order defined dependencies between the tests
#Test
public void serverStartedOk() {}
#Test(dependsOnMethods = { "serverStartedOk" })
public void method1() {}
The above defines the order that serverStartedOk will run before method1..based on the dependsOnMethods...

How to pass spring.config.location="somepath" while building SpringBoot application with command-line Gradle (6.4) build

I have a SpringBoot application where I have application.properties file outside of project (it's not in usual place src/main/resources).
While building application with gradle clean build, it fails as code is not able to find properties files.
I have tried many command to pass vm args, gradle opts but its not working.
gradle clean build -Djvmargs="-Dspring.config.location=/users/home/dev/application.properties" //not working
It fails on test phase when it creates Spring application context and not able to substitute property placeholders. If I skip test as gradle clean build -x test it works.
Though I can run the app with java -jar api.jar --spring.config.location=file:/users/home/dev/application.properties
Please help how I can pass spring.config.location=/users/home/dev/application.properties in gradle build using command line so that build runs with all Junit tests
If I were you, I would not get involved the actual properties to junit test. So I would create a test properties for the project under src/test/resources/application-test.properties and in junit test I would load the test properties.
Example:
#RunWith(SpringRunner.class)
#SpringBootTest(classes = MyProperties.class)
#TestPropertySource("classpath:application-test.properties")
public class MyTestExample{
#Test
public void myTest() throws Exception {
...
}
}
System properties for running Gradle are not automatically passed on to the testing framework. I presume this is to isolate the tests as much as possible so differences in the environment will not lead to differences in the outcome, unless explicitly configured that way.
If you look at the Gradle API for the Test task, you can see that you can configure system properties through through the systemProperty method on the task (Groovy DSL):
test {
systemProperty "spring.config.location", "/path/to/my/configuration/repository/application.properties"
}
If you also want to read a system property from the Gradle command line and then pass that the test, you have to read it from Gradle first, e.g. as a project property, and then pass that value to the test:
test {
if (project.hasProperty('testconfig')) {
systemProperty 'spring.config.location', project.getProperty('testconfig')
}
}
Run it with gradle -Ptestconfig="/path/to/my/configuration/repository/application.properties" build
However, I would discourage using system properties on the build command line if you can avoid it. At the very least, it will annoy you greatly in the long run. If the configuration file can be in different locations on different machines (depending on where you have checkout out the repository and if it is not in the same relative path to your Spring Boot repository), you may want to specify it in a personal gradle.properties file instead.
I think there is a misunderstanding.
spring.config.location is used at runtime
As you validated:
java -jar api.jar --spring.config.location=file:/users/home/dev/application.properties
spring.config.location is used or required at runtime, not at build time.
When your spring boot app is building, an application.properties is required. An approach could be use an src/main/resources/application.properties with template values, but at runtime you will ignore it spring.config.location=file...
For unit tests
In this case as #nikos-bob said, you must use another properties, commonly inside of your src/test/resources
Environment variables instead external properties
We don't want to have hardcoded values in our main git repository src/main/resources/application.properties so the first idea is use an external properties. But this file must be stored in another git repository (equal to main repository ) or manually created.
Spring and other frameworks give us an alternative: Use environment variables.
So instead of manually external creation of application.properties or store it in our git repository, your spring boot app always must have an application.properties but with environment variables:
spring.datasource.url=jdbc:oracle:thin:#${DATABASE_HOST}:${DATABASE_PORT}:${DATABASE_SID}
spring.datasource.username=${DATABASE_USER}
spring.datasource.password=${DATABASE_PASSWORD}
spring.mail.host = ${MAIL_HOST}
spring.mail.username =${MAIL_USERNAME}
spring.mail.password =${MAIL_PASSWORD}
Advantages:
No manually creation of application.properties allowing us a more easy devops automations
No spring.config.location=file.. is required

Spring - Run test from IDE - how to load test properties from a file like 'application-test.properties'

How can I load test properties from a file like 'application-test.properties'?
The file is stored in the src/test/resources folder. I put the file also in all possible folders as well. When running the test as part of the Maven test run, all works fine.
When running the new (single) test from the (IntelliJ) IDE, each time I get same the error message:
Caused by: java.io.FileNotFoundException: class path resource
[application-test.properties] cannot be opened because it does not
exist
This is the test class:
#RunWith(SpringRunner.class)
#EnableAutoConfiguration
#ComponentScan(basePackages = {"nl.deholtmans.tjm1706.todolist"})
#PropertySource( "application-test.properties")
public class TodoListServiceTest {
#Autowired
TodoListService todoListService;
#Test
public void testBasic() { ... }
It looks that I have to run the test first time from Maven. Why is that?
Spring Boot will automatically load the correct properties file if the profile is activated. In a test you can use the #ActiveProfiles annotation for that.
Next you would need to make sure that you actually use the proper Spring Boot infrastructure to run your test, using #SpringBootTest. That being said your test header should look something like the following
#RunWith(SpringRunner.class)
#SpringBootTest
#ActiveProfiles("test")
public class TodoListServiceTest { ... }
And ofcourse make sure that your IDE builds the application before running the tests.

JUnit class is not displayed in JMeter

I have created a Java project with 1 class containing 2 simple tests, exported as jar and added the jar in my JMeter JUnit folder, now after restarting the JMeter i don't see my class in JMeter even after selecting Annotation 4 option.
This is my class:
package print;
import org.junit.Test;
public class PrintClass {
#Test public void test() {
System.out.println("Hello World..!");
}
}
Consider the following checklist:
Your JUnit test class should have either empty constructor or constructor taking a single string as an argument. Other options are not supported
You should place your .jar file(s) under "lib/junit" folder of your JMeter installation
If there are any dependencies you need to put them somewhere in JMeter classpath as well
JMeter restart will be required to pick the .jars up
In case of any problems first of all check jmeter.log file (normally it lives under "bin" folder of your JMeter installation and contains enough troubleshooting information)
See How to Use JUnit With JMeter article for more details.
Even I faced same kind of issue then I added the dependency jars to the lib file.
Make sure you copy these files at this location -> apache-jmeter-5.1.1\lib
1.Selenium webdriver jar file (selenium-server-standalone)
2. Junit4 Jar file (junit4)
Make sure you add Jar file from eclipse or any IDE to this location -> apache-jmeter-5.1.1\lib\junit
1. Jar file which contains the automation selenium code (Using Junit)
Restart Jmeter and continue which the normal process of adding thread group and adding Junit sampler etc...
This resolved my issue and I was able to run my scripts on Jmeter.
In eclipse make sure that you create a JUnit class, not just the class and add junit annotations to this, even i was facing the same issue, it got resolved when i was created a JUnit class and then uploaded my project in JMeter
Did you put the jar in :
/lib/junit
Check you jar by running below command to see if it is ok:
jar -tvf <your jar>
And its dependencies as described in:
JUnit test classes not showing up in JMeter
See this for more details:
http://jmeter.apache.org/usermanual/junitsampler_tutorial.html

pax-exam: are the tests running inside of a bundle?

I have a Maven project that builds a very simple OSGi bundle. No activator; it's only job is to deliver some shared code to an OSGi project. I want to test that I have got the dependencies all set up and embedded correctly.
So, I've added pax-exam to the situation.
I'll paste a unit test shell at the end of this. Is my #Test method in fact running inside of a bundle that is in turn depending on the bundle built in my project?
#RunWith(PaxExam.class)
#ExamReactorStrategy(PerClass.class)
public class CommonBundleTest {
#Configuration
public Option[] config() {
return options(
// this is the current project's result artifact
mavenBundle("com.basistech.osgi", "rosette-common-java-lib"),
junitBundles()
);
}
#Test
public void atest() {
}
}
Are the tests running inside of a bundle: yes
Pax Exam creates a TinyBundle for the Unit test itself. But it doesn't add extra dependencies on any bundle declared in the config method.
If you want to make sure those packages are imported you can alter the way the TinyBundle is build.
#ProbeBuilder
public TestProbeBuilder probeConfiguration(TestProbeBuilder probe) {
// makes sure the generated Test-Bundle contains this import!
probe.setHeader(Constants.IMPORT_PACKAGE, "*,your.extra.package");
return probe;
}
The so-called probe bundle created by Pax Exam on the fly contains all classes from the src/test/java folder containing your test class. The probe bundle manifest has a Dynamic-ImportPackage: * header, so it is not normally required to add explicit imports by means of a probe builder.
Any bundles required by your tests must be provisioned by a configuration option in the #COnfiguration method.
If you want your test to fail immediately when a bundle does not resolve, you can set a config property:
pax.exam.osgi.unresolved.fail = true

Resources