TempDir is null - java

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

Related

#DataProvider in testng at class level

I try to run #Test method, but define #Test at class level with dataProvider attribute and also mention method as a #Test, please take look on below code for more idea
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
#Test(dataProvider="Data")
public class TestAtClassLevel{
#Test
public void testCase(String value) {
System.out.println("Test case");
}
#DataProvider(name="Data")
public Object[][] dataProvider(){
String value[][]=new String[2][1];
value[0][0]="FirstValue";
value[1][0]="SecondValue";
return value;
}
}
I try to run the above code but I get the below exception:
[Utils] [ERROR] [Error] org.testng.TestNGException:
Cannot inject #Test annotated Method [testCase] with [class java.lang.String].
I am able to run the above code after remove #Test from method-level
Why am I getting an exception even if I declare data provider name at class level?
If you wanted the testCase method to get data from the data provider then mention that against the test method itself instead of using it at the class level. Or remove the #Test against the method without removing the annotation at class level, so that the method level annotation do not override the class level configuration.
#Test(dataProvider="Data")
public void testCase(String value) {
System.out.println("Test case");
}
Mentioning dataProviderClass is useful at the class level, when the data providers are defined in a different class and this property would indicate testng to look for data providers in the mentioned class. Still, you need to mention the specific data provider name at the method level itself.

Unable to load properties with Java Spring

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

Need to assign dynamic string value to #PactFolder annotation in Java-Pact Contract test

I need to add a variable value to a class-level annotation "#PactFolder" in a JUnit test. I've been able to achieve the dynamic assignment for this annotation using simple reflection in the #BeforeClass method.
However, This JUnit contract test runs with another annotation (#RunWith(PactRunner.class)). Now, since the #PactFolder annotation's purpose is to pass an absolute path to the PactRunner class, and PactRunner reads the value of #PactFolder at the time of invocation, the reflected variable value is of no use.
import org.junit.BeforeClass;
import org.junit.runner.RunWith;
import au.com.dius.pact.provider.junit.PactRunner;
import au.com.dius.pact.provider.junit.Provider;
import au.com.dius.pact.provider.junit.loader.PactFolder;
import au.com.dius.pact.provider.junit.loader.PactSource;
import au.com.dius.pact.provider.junit.target.HttpTarget;
import au.com.dius.pact.provider.junit.target.TestTarget;
#PactFolder("<Dynamic value>")
#RunWith(PactRunner.class)
#Provider("CvSaveDataServiceProvider")
public class ContractTest {
#BeforeClass
public static void setConditions() {
PactFolder pactFolder = ContractTest.class.getAnnotation(PactFolder.class);
AlterPactFolderAnnotation.setAbsolutePactDirectory(ContractTest.class, PactFolder.class, ContractDirectoryRelativeModulePath.HRIS.getRelativeModulePath(), pactFolder);
System.out.println(ContractTest.class.getAnnotation(PactFolder.class).value());
}
#TestTarget
public HttpTarget target = new HttpTarget(8080);
}
I need to access contracts from a locally cloned repository, kept in multiple directories, with final aim to add paths of all directories in a single config file and initialize all tests in different directories from a single point using "mvn test" command (a simple batch file)
Is there a possible solution or any workaround to do this ?

Unit Testing with different behaviour on existance of a file

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);
}
}

Which specific packages are sealed when sealing a .jar?

When sealing a .jar file (the whole .jar, not specific packages), which packages are actually sealed? Is it only the packages that contain .class files, or does it also include parent packages and sub-packages?
To give an example, say I have a .jar containing the single .class file com.company.city.london.class, is it only the com.company.city package that is sealed?
Would the JVM allow me to create and instantiate the class com.company.city.building.house.class outside of the .jar?
Would the JVM allow me to create and instantiate the class com.company.world.class outside of the .jar?
OK, after writing a test application, I have the answers. And they weren't quite what I had expected after reading the documentation.
I have the following two classes packaged into a .jar that has been sealed:
TestClass.java:
package com.company.testjar;
public class TestClass {
}
TestClass2.java:
package com.company.testjar2;
public class TestClass2 {
}
The .jar manifest looks like this:
Manifest-Version: 1.0
Ant-Version: Apache Ant 1.9.3
Created-By: 1.8.0_40-b26 (Oracle Corporation)
Implementation-Vendor: Company
Implementation-Title: Test Jar
Implementation-Version: 6.4.0.0
Sealed: true
According to the documentation, sealing the entire .jar seals ALL packages within the .jar. However, this statement is ambiguous as I found out.
I then wrote some JUnit test cases to see what other classes I could define without causing issues with the sealed .jar.
For my unit tests, I also added the following three test classes. Note that these are NOT defined in the .jar, but do use the same package structure - this is important for the tests.
Bogus.java:
package com.company.testjar;
public class Bogus {
}
SubBogus.java
package com.company.testjar.subpackage;
public class SubBogus {
}
ParentBogus.java:
package com.company;
public class ParentBogus {
}
The JUnit tests:
package com.company.test;
import static org.junit.Assert.*;
import org.junit.Test;
import com.company.ParentBogus;
import com.company.testjar.Bogus;
import com.company.testjar.TestClass;
import com.company.testjar.subpackage.SubBogus;
import com.company.testjar2.TestClass2;
/**
* A set of tests for testing the effects of .jar sealing.
*
* These tests rely on a built .jar named TestJar.jar which is built from the command line.
*
* Only one of these tests can be run at a time because one a package has been loaded, it cannot
* be unloaded again. Because of this, each test must be run separately.
*/
public class TestPackages {
#Test
public void SealedFail1() {
// Instantiate instance of TestClass from sealed .jar.
TestClass t = new TestClass();
// Following should blow up because package com.company.testjar has already
// been loaded by instantiating TestClass above.
try {
new Bogus();
// Should not get here. Throw if we do.
assertFalse(true);
} catch (SecurityException ex) {
// Expected.
}
}
#Test
public void SealedFail2() {
Bogus b = new Bogus();
// Following should blow up because package com.company.testjar has already
// been loaded by instantiating Bogus above.
try {
new TestClass();
// Should not get here. Throw if we do.
assertFalse(true);
} catch (SecurityException ex) {
// Expected.
}
}
/**
* Test to see if instantiating object from package in a sealed .jar will effectively
* load and seal all packages in that .jar.
*/
#Test
public void SealedFail3() {
// Instantiate object from com.company.testjar2 package. This package will now be
// loaded and sealed.
TestClass2 t2 = new TestClass2();
// Instantiate object from com.company.testjar package NOT from sealed .jar.
// This should work because this package has not been sealed yet!
Bogus b = new Bogus();
// This should now throw because the com.company.testjar package has already
// been loaded by instantiating Bogus above, and the TestClass is from that
// same package from the sealed .jar.
try {
new TestClass();
// Should not get here. Throw if we do.
assertFalse(true);
} catch (SecurityException ex) {
// Expected.
}
}
/**
* Test to see if instantiating an object from a sealed .jar prevents us from then
* instantiating an instance of an object from a sub-package NOT defined in the
* same .jar.
*/
#Test
public void SubPackage() {
// Instantiate instance of TestClass from sealed .jar. Loads and seals the
// com.company.testjar package.
TestClass t = new TestClass();
// Now attempt to instantiate an instance of an object from a sub-package of
// com.company.testjar which is not defined in the same .jar.
new SubBogus();
}
/**
* Test to see if instantiating an object from a sealed .jar prevents us from then
* instantiating an instance of an object from a parent package NOT defined in the
* same .jar.
*/
#Test
public void ParentPackage() {
// Instantiate instance of TestClass from sealed .jar. Loads and seals the
// com.company.testjar package.
TestClass t = new TestClass();
// Now attempt to instantiate an instance of an object from the parent-package of
// com.company.testjar which is not defined in the same .jar.
new ParentBogus();
}
}
The individual tests should be run independently because once a package has been loaded, I'm not unloading it again and would affect the result of the tests. If you run all the tests in once go, there will be failures because packages are loaded by the first test and stay loaded.
All of the tests pass when run individually.
From these tests, we can determine the following:
Sealing an entire .jar does not seal the empty parent packages. So the following empty packages are not sealed : 'com' and 'com.company'. Only packages that contain classes are sealed. See test ParentPackage().
If you load a package from a .jar by instantiating a class from it, and then attempt load a class from the same package external to the .jar, this will fail. See test SealedFail1().
If you load a package externally from the .jar by instantiating a class that shares the same package name as a .class within the .jar, attempting to then instantiate a class from the sealed .jar from that same package will fail. See test SealedFail2().
Instantiating an object from a sealed .jar only loads (and seals) the package that that specific class is located in. No other packages from the same .jar are loaded at the same time. See test SealedFail3().
You can successfully instantiate objects defined in a sub-package of an already sealed and loaded package from a .jar without issue. See test SubPackage().

Categories