I am a complete newbie to Spring. I am trying to figure out how to access properties from props files injected into my app through Spring.
I wrote a simple test provided below. I run it by passing location of the properties file through environment variables provided at JRE options
$ mvn test -DSPRING_CONFIG_NAME=my_spring \
-DSPRING_CONFIG_LOCATION=file:///Users/desilets/Documents/conf
Here is the content of the my_spring.properties file
$ cat /Users/desilets/Documents/conf/my_spring.properties
my.spring.greeting=hello world
When I run the test, it fails. Yet the output indicates that the environment variables were well received:
SPRING_CONFIG_NAME=my_spring
SPRING_CONFIG_LOCATION=file:///Users/desilets/Documents/conf
greeting=null
What am I doing wrong?
Thx.
---- Code for the test ---
import org.junit.Assert;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Value;
public class AccessPropertiesTest {
#Value("${my.spring.greeting}")
String greeting;
#Test
public void test__LoadProperties() throws Exception {
System.out.println("SPRING_CONFIG_NAME="+
System.getProperty("SPRING_CONFIG_NAME"));
System.out.println("SPRING_CONFIG_LOCATION="+
System.getProperty("SPRING_CONFIG_LOCATION"));
System.out.println("greeting="+greeting);
Assert.assertEquals(
"The property my.spring.greeting was not read correctly",
greeting, "hello world");
}
}
If its a spring project there would be two locations for properties
src/main/resources
src/test/resources
If you run tests it will pick from src/test/resources.
#RunWith(SpringRunner.class)
#DataJpaTest
public class AccessPropertiesTest {
#Value("${my.spring.greeting}")
String greeting;
.....
}
refer https://www.baeldung.com/spring-boot-testing
add: my.spring.greeting=anyValue into application.properties or application.properties.yaml file
Related
I want to copy some files into a temporary directory. But the File I annotate with #TempDir does not seem to get injected.
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
import java.io.File;
public class MyTempFileTest {
#TempDir
public File tempFolder;
#Test
public void testTempFolder() {
Assertions.assertNotNull(tempFolder);
}
}
the result is org.opentest4j.AssertionFailedError: expected: not <null>
I would instead expect it to be a random temporary directory, as was the case with #Rule TemporaryFolder tmpSudokus = new TemporaryFolder() in Junit4.
And according to the docs I can annotate a Java.io.File.
If I try to pass the tempDir as a directory
#Test
public void testTempFolderParam(#TempDir File tempFolder) {
Assertions.assertNotNull(tempFolder);
}
I get org.junit.jupiter.api.extension.ParameterResolutionException: No ParameterResolver registered for parameter [java.io.File tempFolder] in executable [public void my.package.MyTempFileTest.testTempFolderParam(java.io.File)].
The test is part of an android project, my dependencies are:
dependencies {
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.7.2'
testImplementation 'org.junit.jupiter:junit-jupiter-params:5.7.2'
}
According to documentation Junit5 Docs
The temporary directory is only created if a field in a test class or a parameter in a lifecycle method or test method is annotated with #TempDir. If the field type or parameter type is neither Path nor File or if the temporary directory cannot be created, an ExtensionConfigurationException or a ParameterResolutionException will be thrown as appropriate. In addition, a ParameterResolutionException will be thrown for a constructor parameter annotated with #TempDir.
As I see in your example, you did use java.io.File so I guess your problem is in the creation part of the temporary folder.
I copied your example and it did work, the tempDir was not null
Dependencies :
junit-jupiter:5.7.2
junit-jupiter-engine:5.7.2
junit-jupiter-params:5.7.2
This has been puzzling me for half a day now. I can't seem to find the issue. Basically I have my Test runner, feature file, and the steps file in my workspace. The java files are in the same package (i.e. no package).
Below is my TestRunner.java
import org.junit.Test;
import org.junit.runner.RunWith;
import cucumber.api.CucumberOptions;
import cucumber.api.junit.Cucumber;
#RunWith(Cucumber.class)
#CucumberOptions(features = "test/resources/features", tags = { "~#Ignore" })
public class TestRunner {
#Test
public void feature() {
}
}
My feature file, helloWorld.feature
Feature: Simple Test Feature
Scenario: Run Scenario ONE
GIVEN step one
WHEN step two
THEN step three
and my steps file CucumberJava.java,
import cucumber.api.java.en.Given;
import cucumber.api.java.en.Then;
import cucumber.api.java.en.When;
public class CucumberJava {
#Given("^step one$")
public void step_one() {
System.out.println("step one");
}
#When("step two")
public void step_two() {
System.out.println("step two");
}
#Then("^step three$")
public void step_three() {
System.out.println("step three");
}
}
When I execute TestRunner.java as JUnit, everything passes, but I get the following in the console:
0 Scenarios
0 Steps
0m0.000s
WHY? In fact, when I remove CucumberJava.java from the project, I get the exact same output. What am I missing?
I also tried setting the glue option in TestRunner.java code too; still the same result.
Your help is highly appreciated.
The feature file words like Given etc are in uppercase in your feature file. They need to be like Given ie sentence case.
Feature: Simple Test Feature
Scenario: Run Scenario ONE
Given step one
When step two
Then step three
Also you might need to append a 'src' to the feature path in the runner. Like this features = "src/test/resources/features", if you are using Maven. Also no need to have a #Test annotation and method inside the runner.
There are some cases that the software shall behave differently according to some environmental conditions, for example whether a file exists at some place or not.
In my case, I'm developing a library, and it is configured according to a configuration file in classpath, (and falls back to default behavior if the config file does not exists).
How shall I unit test this class?
I need to write tests for evaluating the class in following cases:
the file does not exists on classpath
the file with content A exist on classpath
the file with content B exist on classpath
But I don't know how to configure environment to justify all of them. And execute the test one after each other.
By the way I'm using Java, and I have both JUnit and TestNG on the test classpath.
Edit:
One of the problems is that the config file resides in classpath, so if the normal ClassLoader finds and loads it, it returns the same content as long as the same class loader is used.
And I believe using a custom ClassLoader for testing is so complicated, that it needs tests to validate the tests!
You can use a temporary file created by your test to mock out the path in your class.
ConfigurationTest.java:
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import static org.junit.Assume.assumeThat;
import java.nio.file.Files;
import org.junit.Test;
public class ConfigurationTest {
private Configuration config = new Configuration();
#Test
public void testWithConfigFile() throws Exception {
config.configFile = Files.createTempFile("config_",".ini");
config.configFile.toFile().deleteOnExit();
assertFalse(config.isInDefaultMode());
}
#Test
public void testWithoutConfigFile() throws Exception {
assumeThat(Files.exists(config.configFile), is(false));
assertTrue(config.isInDefaultMode());
}
}
Configuration.java:
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
public class Configuration {
Path configFile = Paths.get("config.ini");
public boolean isInDefaultMode() {
return !Files.exists(configFile);
}
}
My requirement is to run Cucumber test cases using Spring boot to run through a Custom java main class.
I am able to run Cucumber test suite fine if i am using following config class:-
#RunWith(Cucumber.class)
#CucumberOptions(
plugin = {
"html:target/cucumber-html-report",
"json:target/cucumber.json", "pretty:target/cucumber-
pretty.txt",
"usage:target/cucumber-usage.json", "junit:target/cucumber-
results.xml" },
features = { "src/test/resources" },
tags = {"#passed"},
glue = "cucumberTest.steps")
public class RunGwMLCompareTests {
}
And following class to load
#RunWith(SpringRunner.class)
#ActiveProfiles("dev")
#SpringBootTest(classes = Application.class)
public class AbstractDefinitions {
public AbstractDefinitions() {
}
}
And when i run RunGwMLCompareTests class,Now using this config my Cucumber test cases are running , It loads my Spring boot context and then exceutes all cases defined in feature.
Now my issue is that i want to run this from seperate main java class. I have created my java class as follows :-
package cucumberTest;
import cucumber.runtime.ClassFinder;
import cucumber.runtime.RuntimeOptions;
import cucumber.runtime.io.MultiLoader;
import cucumber.runtime.io.ResourceLoader;
import cucumber.runtime.io.ResourceLoaderClassFinder;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class CucumberMainTest {
public static void main(String[] args) throws IOException {
ClassLoader classLoader = CucumberMainTest.class.getClassLoader();
ResourceLoader resourceLoader = new MultiLoader(classLoader);
ClassFinder classFinder = new
ResourceLoaderClassFinder(resourceLoader, classLoader);
List<String> pluginList = new ArrayList<>();
pluginList.add("--plugin");
pluginList.add("html:target/cucumber-html-report");
pluginList.add("--plugin");
pluginList.add("json:target/cucumber.json");
RuntimeOptions ro = new RuntimeOptions(pluginList);
ro.getFilters().add("#passed");
ro.getFeaturePaths().add("src/test/resources");
ro.getGlue().add("cucumberTest/steps");
cucumber.runtime.Runtime runtime = new
cucumber.runtime.Runtime(resourceLoader, classFinder, classLoader,
ro);
runtime.run();
}
}
It executes my test cases but does not load my SpringContext, as a result no spring beans are loadedand i get null pointer exception.. Any help is geatly appreciated.
Regards,
Vikram Pathania
One solution i found was to run RunGwMLCompareTests class from outside which handles my Spring context automatically.
So basically i am using gradle to create batch file which does nothing but automatically creates a batch with all relative depencies in my class path and then run following command:
"%JAVA_EXE%" -classpath "%CLASSPATH%" org.junit.runner.JUnitCore
cucumberTest.runners.RunGwMLCompareTests
where,
JAVA_EXE=C:\Program Files\Java\jdk1.7.0_65/bin/java.exe
And CLASSPATH is lib folder where all jars are present.
CLASSPATH=%APP_HOME%\lib\*.jar
Now running this batch i am using
features = { "src/test/resources" } <tag>
to put my feature files outside so that it can edited on the fly.
I hope this helps somebody out there.
by doing this , i am able to run RunGwMLCompareTests class.
Now using this config my Cucumber test cases are running and It also loads my Spring boot context and then exceutes all cases defined in feature.
Regards,
Vikram Pathania
I try to add a new custom command to the spring boot remote shell without success.
In the documentation is only a groovy example available but I like to use Java do create a new command.
http://docs.spring.io/spring-boot/docs/current/reference/html/production-ready-remote-shell.html
I also check the CRaSH documentation: http://www.crashub.org/1.3/reference.html#_java_commands
I put my class under package commands and crash.commands but I don't see my new command if I connect to the shell via ssh and type help. Any idea what I'm doing wrong?
Here is my Java Code:
package commands;
import org.crsh.cli.Command;
import org.crsh.cli.Usage;
import org.crsh.command.BaseCommand;
import org.springframework.stereotype.Component;
#Component
public class hello extends BaseCommand {
#Command
#Usage("Say Hello")
public String test() {
return "HELLO";
}
}
If your class is called 'hello', put it in
resources/crash/commands/hello/hello.java
Having a package statement doesn't matter.
You don't have to put anything inside src, just have this inside resources.
#Component isn't required.
This class is compiled during runtime. See:
org.crsh.lang.impl.java.JavaCompiler#compileCommand
Therefor any dependency injection requirements need to be considered accordingly with lazy initialization.
Put the class in the default package (i.e. omit the package statement) and put the Java source for the class in src/main/resources/commands. Spring/Crash will compile the Java code the first time you invoke the command. Also, if the class implements a single command the method name should be ‘main’ otherwise users have to type:
> hello test
You also don't need the #Component annotation on the class as it is not a Spring managed bean.