powerMockito mock File objects - java

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.

Related

Error while executing dynamically created JUnit Tests

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

Testing ClassNotFound Exception

I'm trying to test that a class is not found with UnitTest on Android.
What's going on:
1. I'm writing an android library with transitive dependencies which are resolved in the host application
2. The developer may remove some dependencies for example remove all com.example.package
3. I have a Factory that will try to instantiate (using reflection) an Object and catch the ClassNotFoundException. If the developer remove the dependencies, the exception should be thrown.
4. I want to test this case, but all I found is issue with dependencies, not how to test for it.
Example code I want to test
try {
sNetworkResponseBuilderClass = OkHttpNetworkResponse.Builder.class;
} catch (Exception e){
// <<<< I want to test this case
new ClassNotFoundException("Unable to find OkHttpNetworkResponse.Builder.class").printStackTrace();
return null;
}
library used: hamcrast, mockito, JUnit 4.
Do you know how to do it?
So for me the first thing you need to do is to extract the part of the code that can throw a ClassNotFoundException in order to be able to easily mock it, something like:
public Class<? extends NetworkResponseBuilder> getNetworkResponseBuilderClass()
throws ClassNotFoundException {
// Your logic here
}
Then you can test a real factory instance using Mockito.spy to be able to redefine the behavior of the method getNetworkResponseBuilderClass() as next:
public void testFactoryIfNetworkResponseBuilderNotFound() {
Factory factory = spy(new Factory());
when(factory.getNetworkResponseBuilderClass()).thenThrow(
new ClassNotFoundException()
);
// The rest of your test here
}
public void testFactoryIfNetworkResponseBuilderFound() {
Factory factory = spy(new Factory());
when(factory.getNetworkResponseBuilderClass()).thenReturn(
OkHttpNetworkResponse.Builder.class
);
// The rest of your test here
}
More details about Mockito.spy.
Not quite sure if I understood your question correctly, but you can check with JUnit if an exception gets thrown:
#Test(expected=ClassNotFoundException.class)
public void testClassNotFoundException() {
// a case where the exception gets thrown
}
OkHttpNetworkResponse.Builder might be as follows:
package com.example.model;
public class OkHttpNetworkResponse {
public static class Builder {
}
}
I have a Factory that will try to instantiate (using reflection) an Object and catch the ClassNotFoundException. If the developer remove
the dependencies, the exception should be thrown.
Factory Class: which will create any object might be as follows:
package com.example.factory;
public class Factory {
public static Object getInstance(String className)
throws ClassNotFoundException, InstantiationException,
IllegalAccessException {
Class clazz = Class.forName(className);
return clazz.newInstance();
}
}
The developer may remove some dependencies for example remove all com.example.package
I want to test this case, but all I found is issue with dependencies, not how to test for it.
FactoryTest Class: which will test whether ClassNotFoundException is thrown or not might be as follows: N.B: please Check the comments carefully.
package com.example.factory;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.io.File;
import java.io.IOException;
import org.junit.Test;
public class FactoryTest {
Factory factory;
#Test(expected=ClassNotFoundException.class)
public void test() throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException {
ClassLoader loader = FactoryTest.class.getClassLoader();
String directory = loader.getResource(".").getPath() + "/com/example/model";
File dir = new File(directory);
//Checking directory already existed or not..
assertTrue("Directory:"+dir.getPath()+" not exist",dir.exists());
//Deleting directory
deleteDirectoryProgramatically(directory);
//Checking directory already deleted or not..
assertFalse("Directory:"+dir.getPath()+" still exist",dir.exists());
//Now getInstance Method will throw ClassNotFoundException because OkHttpNetworkResponse.Builder.class has been deleted programatically.
Factory.getInstance("OkHttpNetworkResponse.Builder.class");
}
private void deleteDirectoryProgramatically(String directory) {
File dir = new File(directory);
System.out.println(dir.getAbsolutePath());
String[] files = dir.list();
for (String f : files) {
File fl = new File(directory,f);
System.out.println(f+ " deleted?"+fl.delete());
}
System.out.println(dir+ " deleted?"+dir.delete());
}
}
It is very simple issue. JUnit4 exception unit testing is given below with an example. Hope it will clarify you.
MyNumber.java
public class MyNumber {
int number;
public MyNumber div(MyNumber rhs) {
if (rhs.number == 0) throw new IllegalArgumentException("Cannot divide by 0!");
this.number /= rhs.number;
return this;
}
}
MyNumberTest.java
public class MyNumberTest {
private MyNumber number1, number2; // Test fixtures
#Test(expected = IllegalArgumentException.class)
public void testDivByZero() {
System.out.println("Run #Test testDivByZero"); // for illustration
number2.setNumber(0);
number1.div(number2);
}
}
JUnit - Exceptions Test
To test if the code throws a desired exception, use annotation #Test(expected = exception.class), as illustrated in the previous example. For your case it will be
/**
* Check for class not found exception
**/
#Test(expected=ClassNotFoundException.class)
public void testClassNotFoundException() {
.....
}
For better understanding, you can go through this tutorial: Java Unit
Testing - JUnit & TestNG. It contains full running code example
step by step with explanation.
inside catch you can check the object with the instanceof operator as :
try {
sNetworkResponseBuilderClass = OkHttpNetworkResponse.Builder.class;
} catch (Exception e){
if(e instanceof ClassNotFoundException){
// here you can do the code you want in case of ClassNotFoundException thrown
}
}
it is your dictionary problem. in your dictionary in test class will not have . change your dictionary.
Use Class.forName("com.example.ClassName")
try {
Class.forName("com.example.OkHttpNetworkResponse.Builder");
} catch (ClassNotFoundException e) {
// This class was not found
}
See Class.forName(String className)

Defined Global variable, however unable to use it. Please suggest

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

JUnit: Run one test with different configurations

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.

How to handle ordering of #Rule's when they are dependent on each other

I use embedded servers that run inside Junit test cases. Sometimes these servers require a working directory (for example the Apache Directory server).
The new #Rule in Junit 4.7 can handle these cases. The TemporaryFolder-Rule can create a temporary directory. A custom ExternalResource-Rule can be created for server. But how do I handle if I want to pass the result from one rule into another:
import static org.junit.Assert.assertEquals;
import java.io.*;
import org.junit.*;
import org.junit.rules.*;
public class FolderRuleOrderingTest {
#Rule
public TemporaryFolder folder = new TemporaryFolder();
#Rule
public MyNumberServer server = new MyNumberServer(folder);
#Test
public void testMyNumberServer() throws IOException {
server.storeNumber(10);
assertEquals(10, server.getNumber());
}
/** Simple server that can store one number */
private static class MyNumberServer extends ExternalResource {
private TemporaryFolder folder;
/** The actual datafile where the number are stored */
private File dataFile;
public MyNumberServer(TemporaryFolder folder) {
this.folder = folder;
}
#Override
protected void before() throws Throwable {
if (folder.getRoot() == null) {
throw new RuntimeException("TemporaryFolder not properly initialized");
}
//All server data are stored to a working folder
File workingFolder = folder.newFolder("my-work-folder");
dataFile = new File(workingFolder, "datafile");
}
public void storeNumber(int number) throws IOException {
dataFile.createNewFile();
DataOutputStream out = new DataOutputStream(new FileOutputStream(dataFile));
out.writeInt(number);
}
public int getNumber() throws IOException {
DataInputStream in = new DataInputStream(new FileInputStream(dataFile));
return in.readInt();
}
}
}
In this code the folder is sent as a parameter into the server so that the server can create a working directory to store data. However this does not work because Junit processes the rules in reverse order as they are defined in the file. The TemporaryFolder Rule will not be executed before the server Rule. Thus the root-folder in TempraryFolder will be null, resulting that any files are created relative to the current working directory.
If I reverse the order of the attributes in my class I get a compile error because I cannot reference a variable before it is defined.
I'm using Junit 4.8.1 (because the ordering of rules was fixed a bit from the 4.7 release)
EDIT: With the recently released Junit 4.10, you can use RuleChain to chain rules correctly (see at the end).
You could introduce another private field without the #Rule annotation, then you can reorder your code as you wish:
public class FolderRuleOrderingTest {
private TemporaryFolder privateFolder = new TemporaryFolder();
#Rule
public MyNumberServer server = new MyNumberServer(privateFolder);
#Rule
public TemporaryFolder folder = privateFolder;
#Test
public void testMyNumberServer() throws IOException {
server.storeNumber(10);
assertEquals(10, server.getNumber());
}
...
}
The cleanest solution is to have a compound rule, but the above should work.
EDIT: With the recently released Junit 4.10, you can use RuleChain to chain rules correctly:
public static class UseRuleChain {
#Rule
public TestRule chain = RuleChain
.outerRule(new LoggingRule("outer rule"))
.around(new LoggingRule("middle rule"))
.around(new LoggingRule("inner rule"));
#Test
public void example() {
assertTrue(true);
}
}
writes the log
starting outer rule
starting middle rule
starting inner rule
finished inner rule
finished middle rule
finished outer rule
To make the rules dependent, your have to initialize them first and create the dependency relationships using contructors or (depending on you rule) fluent builders. The dependency relations have to be defined in the field-initialization and could not be created in #Before methods as those are executed after rule application. To force the correct ordering of rule execution, you have to define the rule chain.
public class FolderRuleOrderingTest {
private TemporaryFolder folder = new TemporaryFolder();
//assume, we have a rule that creates a testfile in a temporary folder
//we create a dependency relationship between file and folder,
//so that file depends on folder
private TemporaryFile file = new TemporaryFile(folder, "testfile.txt");
//the rule chain ensures, the temporary folder is created before and removed
//after the testfile has been created and deleted (or whatever)
#Rule
public RuleChain chain= RuleChain.outerRule(folder).around(file));
#Test
public void testFileExist() throws IOException {
assertTrue(file.getFile().exist());
}
...
}
If you will not find normal solution, you can always create compound rule (and the only one having #Rule annotation) that contains all others and executes them in order.
You can also use the attribute order since 4.13:
You can use order() if you want to have control over the order in which the Rules are applied.
public class ThreeRules {
#Rule(order = 0)
public LoggingRule outer = new LoggingRule("outer rule");
#Rule(order = 1)
public LoggingRule middle = new LoggingRule("middle rule");
#Rule(order = 2)
public LoggingRule inner = new LoggingRule("inner rule");
// ...
}
Alternatively, you could simply offer a setter in your MyNumberServer rule instead of giving the folder in the constructor.
Furthermore, ordering amongst rules is not guaranteed the way you described. It can become a little tricky, especially when you want some communication between your rules, see e.g. Best way of logging exceptions when tests fail (e.g. using a junit rule).

Categories