I am newbie to Java and facing below issue. I have following code:
public class ReadExcel {
Config conf = new Config();
String filePath = conf.getInputfilePath();
#Test
public void readFullXL() {
try {
FileInputStream FSRead = new FileInputStream(filePath);
I have declared this variable ‘filePath’ outside function because; I want to use it as global variable.
However, inside readFullXL(), I am not able to get value for variable ‘filePath’ and getting null pointer exception.
Can somebody suggest? How I can declare global variable in Junit file.
Edit:
Of course first you gotta check that your getInputfilePath() method does not return null.
Further: I suggest you go ahead and read some informations on UnitTesting (JUnit - Tutorial).
If it's just one test you could just instantiate your needed classes within that test.
#Test
public void readFullXL() {
Config conf = new Config();
FileInputStream FSRead = new FileInputStream(conf.getInputfilePath());
//...
}
If you have multiple tests relying on the same fixture you can go ahead and implement a setup method using the #Before annotation. The setup method will then be called before every test (#Test annotation) method.
class ReadExcel {
Config conf;
#Before
public void setUp() {
conf = new Config();
}
#Test
public void readFullXL() {
//...
FileInputStream FSRead = new FileInputStream(conf.getInputfilePath());
// Run your test
}
}
Thank you for your response and time.
I got it working by creating interface between config and ReadExcel file.
Also removed Junit test annotation from config file that was not required.
Thanks,
Ashvini
Related
I am trying to invoke a dynamically created Junit test class using the code below
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
URL classUrl = javaClass.getParent().toFile().toURI().toURL();
URLClassLoader classLoader = URLClassLoader.newInstance(new URL[] { classUrl });
Class<?> clazz = Class.forName(fileName, true, classLoader);
Object obj = clazz.newInstance();
context.getLogger().log("Test Class Loader==>"+obj.getClass().getClassLoader()+"\n");
JUnitCore junit = new JUnitCore();
context.getLogger().log("JUnitCore Class Loader==>"+junit.getClass().getClassLoader()+"\n");
junit.addListener(new TextListener(new PrintStream(outputStream)));
Result result = junit.run(clazz);
return outputStream.toString();
Dynamically created test file
public class SampleJavaFileTest {
String EXPECTED_OUTPUT_STRING="r3plac3";
#Test
public void testReplaceString() {
SampleJavaFile sample = new SampleJavaFile();
String outputString = sample.replaceString("replace","e","3");
Assert.assertEquals(EXPECTED_OUTPUT_STRING, outputString);
}
}
But I get the error as
There was 1 failure:
1) initializationError(JUnitTest)
org.junit.runners.model.InvalidTestClassError: Invalid test class 'JUnitTest':
1. No runnable methods
at org.junit.runners.ParentRunner.validate(ParentRunner.java:511)
at org.junit.runners.ParentRunner.<init>(ParentRunner.java:101)
at org.junit.runners.BlockJUnit4ClassRunner.<init>(BlockJUnit4ClassRunner.java:84)
at org.junit.runners.JUnit4.<init>(JUnit4.java:23)
at org.junit.internal.builders.JUnit4Builder.runnerForClass(JUnit4Builder.java:10)
at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:70)
at org.junit.internal.builders.AllDefaultPossibilitiesBuilder
.runnerForClass(AllDefaultPossibilitiesBuilder.java:37)
at org.junit.runner.Computer.getRunner(Computer.java:50)
at org.junit.runner.Computer$1.runnerForClass(Computer.java:31)
at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:70)
at org.junit.runners.model.RunnerBuilder.runners(RunnerBuilder.java:125)
at org.junit.runners.model.RunnerBuilder.runners(RunnerBuilder.java:111)
at org.junit.runners.Suite.<init>(Suite.java:81)
at org.junit.runner.Computer$2.<init>(Computer.java:33)
I tried printing the class loaders of the dynamically created class and the JUnitCore class the results are
Test Class Loader==>java.net.FactoryURLClassLoader#86be70a
JUnitCore Class Loader==>java.net.URLClassLoader#49c2faae
Upon going through various posts the answers provided are to use custom class loaders to resolve this issue. Can you assist on how to create a custom class loader to resolve this issue?
If not custom class loaders , how else can this be resolved?
Thanks!
This might be class loader related issue, try to create URLClassLoader by using constructor and pass class loader of other test class (or just junit class) as is parent class loader, to ensure that JUnit classes are always loaded by the same class loader. And double check that this is right annotation, with right package.
public URLClassLoader(URL[] urls, ClassLoader parent)
so
new URLClassLoader(urlOfToClass, SomeTestOrJUnitClass.class.getClassLoader())
https://docs.oracle.com/javase/7/docs/api/java/net/URLClassLoader.html#URLClassLoader(java.net.URL[],%20java.lang.ClassLoader)
this exception is generated in this junit block of code
List<Method> methods = testClass.getAnnotatedMethods(Test.class);
if (methods.size() == 0) {
errors.add(new Exception("No runnable methods"));
}
So, I'd recommend to double check, that you definitely have annotation #Test for method, and it is really org.junit.Test and this annotation available in runtime.
You can check this by taking klass.getDeclaredMethod("testReplaceString") and printing all annotations from it.
If it doesn't help, then, you can debug Junit library, put breakpoint to exception (please note, this exceptions generated not in the same place, where throwed) and check conditions
BTW, what version of junit do you use?
EDITED:
I've checked your code, I've created a new project in IDEA, added junit 4.13-rc-1 to dependencies and created two files.
public class SampleJavaFileTest {
String EXPECTED_OUTPUT_STRING="r3plac3";
#Test
public void testReplaceString() {
Assert.assertEquals(EXPECTED_OUTPUT_STRING, "r3plac3");
}
}
and another class
public class ClassLoadDynamically {
public static void main(String[] args) throws Exception {
final File fileForClass = new File(SampleJavaFileTest.class.getProtectionDomain().getCodeSource().getLocation().getPath());
URLClassLoader classLoader = URLClassLoader.newInstance(new URL[] { fileForClass.toURI().toURL() });
Class<?> clazz = Class.forName("SampleJavaFileTest", true, classLoader);
Method testReplaceString = clazz.getDeclaredMethod("testReplaceString");
System.out.println("Get declared methods==>"+ testReplaceString);
System.out.println("Get annotation => "+ testReplaceString.getAnnotation(org.junit.Test.class));
JUnitCore junit = new JUnitCore();
Result result = junit.run(clazz);
System.out.println(result.wasSuccessful());
}
}
I've checked your code, it works in this way. Please check, how do you generate your code dynamically, looks like the the issue in wrong bytecode generation, double check, how do you set annotations to the method.
However, I'm not sure, about your environment configuration on lambda. Anyway, I'd recommend to make your code run locally
public class ConnectionPointTest {
#Test
public void testMockito() throws IOException {
DataInputStream dataInputStream = mock(DataInputStream.class);
when(dataInputStream.readUTF()).thenReturn("Test");
new JustTest(dataInputStream).doTest();
}
public class JustTest {
DataInputStream dataInputStream;
public JustTest(DataInputStream dataInputStream) {
this.dataInputStream = dataInputStream;
}
public void doTest() throws IOException {
String s = dataInputStream.readUTF();
System.out.println(s);
}
}
}
I implement JUnit testing + Mockito in the project. Then I try to mock my DataInpuStream, I have an exeption at this code :
when(dataInputStream.readUTF()).thenReturn("Test");
P.S. class JustTest is only for show you what I want to mock.
There is exeption:
java.lang.NullPointerException
at java.io.DataInputStream.readUnsignedShort(DataInputStream.java:337)
at java.io.DataInputStream.readUTF(DataInputStream.java:589)
at java.io.DataInputStream.readUTF(DataInputStream.java:564)
...
You are trying to mock a final method:
public final String readUTF() throws IOException {
return readUTF(this);
}
Mockito (v2.x) supports this but it requires additional configuration. More details in the docs:
Mocking of final classes and methods is an incubating, opt-in feature. It uses a combination of Java agent instrumentation and subclassing in order to enable mockability of these types. As this works differently to our current mechanism and this one has different limitations and as we want to gather experience and user feedback, this feature had to be explicitly activated to be available ; it can be done via the mockito extension mechanism by creating the file src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker containing a single line:
mock-maker-inline
So, create a file named org.mockito.plugins.MockMaker with this content:
mock-maker-inline
Place this file in a folder named mockito-extensions on your test classpath (if you are using Maven just create this folder in src/test/resources)
Re run your test.
With this configuration in place I have successful run your test with:
JUnit 4.12
Mockito 2.7.19
My project folder structure is as below (Selenium +testng)
Proj
--Data folder
---General.properties
--src folder
---libraby package
----library.java
--testcases package
---testcase1 (testng test, extending library)
Problem: Null pointer when reading general properties file in library.java, but same code works fine when placed inside #test method in testcase. Whys is this happening? i want to read the properties inside library only, what should i do? please help.
public class Library{
public static Properties Prop = null;
public static FileInputStream sFileIn = null;
public static final String sProjpath = System.getProperty("user.dir").toString();
public void Initialization () throws Throwable
{
sFileIn = new FileInputStream(sProjpath+"\\Data\\General.properties");
Prop.load(sFileIn);}
The null pointer exception is because the public static Properties Prop = null; makes it null
To overcome this public static Properties Prop = new Properties(); is to be used
May be your are initializing the Prop object somewhere in your test case, so it works fine
I have problem mock whenNew(File.class) using PowerMockito. Here is my method I want to test:
public void foo() {
File tmpFile = new File("Folder");
if (!tmpFile.exists()) {
if (!configFolder.mkdir()) {
throw new RuntimeException("Can't create folder");
}
}
File oneFileInFolder = new File(tmpFile, "fileOne.txt");
if (oneFileInFolder.exists()){
//do something
}
}
Here is test code I wrote:
static File mockFile;
#Before
public void setUp() throws Exception {
//....some code
mockFolder = mock(File.class);
when(mockFolder.getPath()).thenReturn("Folder");
when(mockFolder.exists()).thenReturn(true);
whenNew(File.class).withParameterTypes(String.class).withArguments(anyString()).thenReturn(mockFolder);
//...some code
}
But when I debug my testcase, I still see a real folder created in my pwd. I don't want folders created when I run my testcases. Any idea?
Since you haven't specified this in your question, the following may be missing:
#PrepareForTest(ClassYoureCreatingTheFileInstanceIn.class)
According to the Wiki:
Note that you must prepare the class creating the new instance of MyClass for test, not the MyClass itself. E.g. if the class doing new MyClass() is called X then you'd have to do #PrepareForTest(X.class) in order for whenNew to work.
In other words, X is the class that contains foo() in your example.
I have 2 test methods, and i need to run them with different configurations
myTest() {
.....
.....
}
#Test
myTest_c1() {
setConf1();
myTest();
}
#Test
myTest_c2() {
setConf2();
myTest();
}
//------------------
nextTest() {
.....
.....
}
#Test
nextTest_c1() {
setConf1();
nextTest();
}
#Test
nextTest_c2() {
setConf2();
nextTest();
}
I cannot run them both from one config (as in code below) because i need separate methods for tosca execution.
#Test
tests_c1() {
setConf1();
myTest()
nextTest();
}
I don't want to write those 2 methods to run each test, how can i solve this?
First i thought to write custom annotation
#Test
#RunWithBothConf
myTest() {
....
}
But maybe there are any other solutions for this?
What about using Theories?
#RunWith(Theories.class)
public class MyTest{
private static enum Configs{
C1, C2, C3;
}
#DataPoints
public static Configs[] configValues = Configs.values();
private void doConfig(Configs config){
swich(config){...}
}
#Theory
public void test1(Config config){
doConfig(config);
// rest of test
}
#Theory
public void test2(Config config){
doConfig(config);
// rest of test
}
Not sure why formatting if off.
I have a similar issue in a bunch of test cases I have, where certain tests need to be run with different configurations. Now, 'configuration' in your case might be more like settings, in which case maybe this isn't the best option, but for me it's more like a deployment model, so it fits.
Create a base class containing the tests.
Extend the base class with one that represents the different configuration.
As you execute each of the derived classes, the tests in the base class will be run with the configuration setup in its own class.
To add new tests, you just need to add them to the base class.
Here is how I would approach it:
Create two test classes
The first class configures to conf1 but uses the #Before attribute trigger the setup
The second class extends the first but overrides the configure method
In the example below I have a single member variable conf. If no configuration is run it stays at its default value 0. setConf1 is now setConf in the Conf1Test class which sets this variable to 1. setConf2 is now setConf in the Conf2Test class.
Here is the main test class:
public class Conf1Test
{
protected int conf = 0;
#Before
public void setConf()
{
conf = 1;
}
#Test
public void myTest()
{
System.out.println("starting myTest; conf=" + conf);
}
#Test
public void nextTest()
{
System.out.println("starting nextTest; conf=" + conf);
}
}
And the second test class
public class Conf2Test extends Conf1Test
{
// override setConf to do "setConf2" function
public void setConf()
{
conf = 2;
}
}
When I configure my IDE to run all tests in the package I get the following output:
starting myTest; conf=1
starting nextTest; conf=1
starting myTest; conf=2
starting nextTest; conf=2
I think this gives you what. Each test only has to be written once. Each test gets run twice, once with conf1 and once with conf2
The way you have it right now seems fine to me. You aren't duplicating any code, and each test is clear and easy to understand.