I have method for which I need to create a JUnit test:
public class MyClass {
private String file1;
private String file2;
public void myMethodSpaceCheck(){
if (new File(file1).size() > new File(file2).size() {
throw new Exception .....
}
}
}
Is it possible to use Mockito to create that JUnit test?
When dealing with files in Java, my preferred option is to go with Apache VFS, as I can then treat them as any other POJO. Obviously, that's a lot of work when you are already stuck with the File API.
Another option is to forget Mockito entirely and write those files on the system. I usually avoid that, as it sometimes make it harder to have tests run in parallel on some systems.
For this specific situation, my solution is generally to provide a special class, say FileBuilder, that can instantiate new Files:
public class FileBuilder {
public java.io.File newFile(String pathname) {
return new java.io.File(pathname);
}
}
I then mock this class before passing it to MyClass, and instrument it as appropriate:
#Test(expected = Exception.class)
public void should_fail_when_file1_is_bigger_than_file2() {
FileBuilder mockFile1 = file(2L);
FileBuilder mockFile2 = file(1L);
FileBuilder mockFileBuilder = mock(FileBuilder.class);
when(mockFileBuilder.newFile("file1").thenReturn(mockFile1);
when(mockFileBuilder.newFile("file2").thenReturn(mockFile2);
new MyClass(mockFileBuilder).myMethodSpaceCheck();
}
private static File file(long length) {
File mockFile = mock(File.class);
when(mockFile.length()).thenReturn(length);
return mockFile;
}
(your example mentions File.size(); I assumed you meant File.length())
The actual implementation of MyClass would look like this:
public class MyClass {
private String file1;
private String file2;
private final FileBuilder fileBuilder;
public MyClass() {
this(new FileBuilder());
}
#VisibleForTesting
MyClass(FileBuilder fileBuilder) {
this.fileBuilder = fileBuilder;
}
public void myMethodSpaceCheck() //...
}
Related
I am trying to write the Junit test cases for the class that reads Properties file Here is my code:
public class PropertiesRetreiver {
private String foo = "";
private String foo1 = "";
private static String PROPERTIES_PATH ="data.properties";
public PropertiesRetreiver() throws IOException {
InputStream in = this.getClass().getResourceAsStream(PROPERTIES_PATH);
Properties properties = new Properties();
properties.load(in);
foo = properties.getProperty("foo");
foo1 = properties.getProperty("foo1");
}
public String getfoo() {
return foo;
}
public String getfoo1() {
return foo1;
}
}
Can anyone give me idea about test case scenario I can mock and test? Thank you very much for your help.
Your class actually make 2 things : it loads a property file, and stores some specific properties.
For testing purpose, you could (should?) concentrate on one aspect at a time only, either by splitting these 2 roles in different class (a PropertiesLoader and PropertyStore for example) or at least allow for some injection in your class.
Removing unecessary code from the constructor is always a good idea if you want to properly test your classes :)
ex:
public class PropertiesRetreiver {
private String foo = "";
private String foo1 = "";
private static String PROPERTIES_PATH ="data.properties";
public PropertiesRetreiver() {
}
public void loadProperties() throws IOException {
loadProperties(PROPERTIES_PATH);
}
public void loadProperties(String path) throws IOException {
InputStream in = this.getClass().getResourceAsStream(path);
Properties properties = new Properties();
properties.load(in);
loadProperties(properties);
}
public void loadProperties(Properties properties) {
foo = properties.getProperty("foo");
foo1 = properties.getProperty("foo1");
}
public String getfoo() { return foo; }
public String getfoo1() { return foo1; }
}
This code will be much more easy to test since you can focus on each aspect of the properties load/retreival
I am starting to program a Code Generator for NetBeans 8, and I am having trouble figuring out the best way to test its invoke() method.
The code generator I want to test is basically like this:
(imports here)
public class MyCodeGenerator implements CodeGenerator {
private final JTextComponent textComponent;
private final CompilationController controller;
MyCodeGenerator(final Lookup context) {
textComponent = context.lookup(JTextComponent.class);
controller = context.lookup(CompilationController.class);
}
#Override
public String getDisplayName() {
return "Generate Some Code...";
}
/**
* This will be invoked when user chooses this Generator from Insert Code
* dialog
*/
#Override
public void invoke() {
if (textComponent != null && controller != null) {
controller.toPhase(Phase.RESOLVED);
//do more things with the source code;
}
}
}
I want to use a mocked (Mockito) object for Lookup, to pass to the MyCodeGenerator's constructor. The mock should return the JTextComponent and the CompilationController.
I know I can provide a JTextComponent with the test code, but I hit the wall when I need to provide a CompilationController.
I can create a temporary java source file with the same content as the JTextComponent, but I could not find a way to create a CompilationController (or WorkingCopy) from it.
This is what I tried so far (my test method):
#Test
public void testInvoke() throws ParseException, IOException {
System.out.println("invoke");
final ExtractControllerTask extractTask = new ExtractControllerTask(
Phase.RESOLVED);
final StringBuilder builder = new StringBuilder(100);
final JTextComponent textComponent;
final Document document;
final FileObject javaTestFile;
final OutputStream outputStream;
final JavaSource source;
builder.append("public class Clazz {");
builder.append("private int a = 2;");
builder.append("}");
textComponent = new JTextArea(builder.toString());
document = textComponent.getDocument();
document.putProperty(BaseDocument.MIME_TYPE_PROP, "text/x-java");
javaTestFile = FileUtil.createData(new File(
"/tmp/javaTestSourceFile.java"));
outputStream = javaTestFile.getOutputStream();
outputStream.write(builder.toString().getBytes());
outputStream.flush();
source = JavaSource.forFileObject(javaTestFile);
assertNotNull(source);
source.runUserActionTask(extractTask, true);
assertNotNull(extractTask.controller); //FAILS HERE
}
This is the code for ExtractControllerTask:
private static class ExtractControllerTask implements
Task<CompilationController> {
private final Phase targetPhase;
private CompilationController controller;
private ExtractControllerTask(final Phase phase) {
this.targetPhase = phase;
}
public void run(final CompilationController compControler) {
try {
compControler.toPhase(this.targetPhase);
this.controller = compControler;
} catch (IOException ioe) {
throw new RuntimeException(ioe);
}
}
}
What surprises me is that the run method in ExtractControllerTask is never called.
I really need to test my code but I can't find the proper way. Maybe the approach is completely wrong.
Can anyone suggest how to achieve this?
I'm newbie in reflection. Is there any way to detect where is an specific method invoked? For example:
public class MyClass {
public static void method(){
//DO SOMETHING
}
}
public class Test {
public test(){
MyClass.method();
}
}
public class MyProcessor extends AbstractProcessor {
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
Method method = MyClass.class.getDeclaredMethod("method");
Class classWhereMethodIsInvoked = obtainClassWhereMethodIsInvoked(method);
}
public Class obtainClassWhereMethodIsInvoked(Method method) {
//here I want to search one class that invoke that method, in this case Test.class
}
}
is something like this possible or I am going crazy?
As mentioned in the comments, Apache BCEL is suitable for your problem. Such libraries are often particularly used for determining compile-time information such as method usage and control flow analysis from the generated bytecode, and such information are difficult, if not impossible, to retrieve using reflection. If you use the BCEL solution, you probably no longer require a custom annotation processor.
But since you already seem to be using a custom annotation processor, the whole point of it is to be able to process annotations in the source files. So one way is to define a custom annotation that marks a method being called, and have the custom processor read these annotations to know which classes call which methods:
#CallerClass("MyClass.method")
public class Test {
public test() {
MyClass.method();
}
}
In the above (trivial) example, a custom CallerClass annotation marks that a class calls the method specified in the annotation's element inside parentheses. The annotation processor can read this annotation and construct the caller information.
Yes it doable if you really want it. You can use the classLoader to search through the class path and scan for the method name through all the class files. Below is a very simplistic example to show that it is doable. In the example below I find usage of the "println" method being used in this class. Essentially you can just broaden the scope from one file in my example to all the class files.
public class SearchClasses {
/**
* #param args the command line arguments
*/
public static void main(String[] args) throws FileNotFoundException {
// InputStream is = SearchClasses.class.getClassLoader().getResourceAsStream("resources.SearchClasses.class");
InputStream is = new FileInputStream(new File("build/classes/resources/SearchClasses.class"));
boolean found = false;
Scanner scanner = new Scanner(is);
while (scanner.hasNext()) {
if (scanner.nextLine().contains("println")) {
System.out.print("println found");
found = true;
break;
}
}
if (!found) {
System.out.print("println NOT found");
}
}
public static void testMethod() {
System.out.println("testing");
}
}
In my IDE I had to use the FileInputStream to access the class file I was searching in.... but if you are searching through jar files then you can use the classLoader instead. You would need mechanism to search through all of the class path... this is not impossible but I left it our for brevity.
EDIT: Here is an attempt to get it working completely.. searches all files in class path for your method.
public class SearchClasses {
/**
* #param args the command line arguments
* #throws java.io.FileNotFoundException
*/
public static void main(String[] args) throws FileNotFoundException, IOException {
printAllFileWithMethod("println");
}
public static void printAllFileWithMethod(String methodName) throws FileNotFoundException, IOException {
Enumeration<URL> roots = SearchClasses.class.getClassLoader().getResources("");
List<File> allClassFiles = new ArrayList<>();
while (roots.hasMoreElements()) {
File root = new File(roots.nextElement().getPath());
allClassFiles.addAll(getFilesInDirectoryWithSuffix(root, "class"));
}
for (File classFile : allClassFiles) {
InputStream is = new FileInputStream(classFile);
boolean found = false;
Scanner scanner = new Scanner(is);
while (scanner.hasNext()) {
if (scanner.nextLine().contains(methodName)) {
System.out.print(methodName + " found in " + classFile.getName() + "\n");
found = true;
break;
}
}
}
}
public static void testMethod() {
System.out.println("testing");
}
static List<File> getFilesInDirectoryWithSuffix(File dir, String suffix) {
List<File> foundFiles = new ArrayList<>();
if (!dir.isDirectory()) {
return foundFiles;
}
for (File file : dir.listFiles()) {
if (file.isDirectory()) {
foundFiles.addAll(getFilesInDirectoryWithSuffix(file, suffix));
} else {
String name = file.getName();
if (name.endsWith(suffix)) {
foundFiles.add(file);
}
}
}
return foundFiles;
}
}
You could define your own mechanism. Use a Map to store the caller of each method :
public static Map<Method, List<String>> callStack = new HashMap<Method, List<String>>();
public static void registerCaller(Method m)
{
List<String> callers = callStack.get(m);
if (callers == null)
{
callers = new ArrayList<String>();
callStack.put(m, callers);
}
StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();
callers.add(stackTraceElements[3].getClassName());
}
The target class :
class MyClass
{
public static void method()
{
registerCaller(new Object(){}.getClass().getEnclosingMethod());
// DO SOMETHING
}
}
Some caller classes :
package the.package.of;
class Test
{
public void test()
{
MyClass.method();
}
}
class Foo
{
public void bar()
{
MyClass.method();
}
}
And finally, the test :
new Test().test();
new Foo().bar();
Method method = MyClass.class.getDeclaredMethod("method");
for (String clazz : callStack.get(method))
{
System.out.println(clazz);
}
Prints :
the.package.of.Test
the.package.of.Foo
Well, if you use Eclipse as an IDE, you can find the complete call hierarchy via "Open Call Hierarchy" function. This will find all usages of your method in any open Eclipse projects.
However, if you want to find out during runtime programmatically, then you need to integrate some library, that can statically analyze the bytecode of your classpath for use of your method.
You can obtain stack trace right inside the test method:
public class Test {
public void test() {
System.out.println(getCallerClass());
}
public static String getCallerClass() {
for (StackTraceElement e: Thread.currentThread().getStackTrace()) {
if (!"java.lang.Thread".equals(e.getClassName()) && !e.getClassName().equals(Test.class.getName()))
return e.getClassName();
}
return null;
}
}
Examples below are shamelessly ripped off of java.dzone.com, and modified to suit my needs:
Our interface:
public interface CompressionStrategy
{
public void compressFiles(ArrayList<File> files);
}
Our First Implementation
public class GZipCompressionStrategy implements CompressionStrategy
{
public File compressFiles(ArrayList<File> files)
{
//using GZIP approach
return archive;
}
}
Our Second Implementation:
public class TarCompressionStrategy implements CompressionStrategy
{
public File compressFiles(ArrayList<File> files)
{
//using TAR approach
return archive;
}
}
And this is the use given:
public class CompressionContext
{
private CompressionStrategy strategy;
//this can be set at runtime by the application preferences
public void setCompressionStrategy(CompressionStrategy strategy)
{
this.strategy = strategy;
}
//use the strategy
public File createArchive(ArrayList<File> files)
{
strategy.compressFiles(files);
}
}
Client Class with Main method
public class Client
{
public static void main(String[] args)
{
CompressionContext ctx = new CompressionContext();
File archive;
//we could assume context is already set by preferences
ctx.setCompressionStrategy(new TarCompressionStrategy());
//get a list of files
...
archive = ctx.createArchive(fileList);
ctx. setCompressionStrategy(new GZipCompressionStrategy());
archive = ctx.createArchive(archive);
}
}
Which feels messy, because:
I'm having to reset the strategy each time
The Two strategies may or may not be compatible (in that order, e.g. does it make sense to Tar a GZipped file?)
Creating a third TARGZipStrategy class is ok in principle, but if we had 10 strategies allowing for every other one to be part of a valid XXXCombinedStrategy method, we'd have ~35 different classes.
Is there a neat way to arbitrarily run multiple strategies sequentially within this pattern? For instance if I wanted to create a .tar.gzip file at the end?
What I'm trying to say is there neat way to combine two strategies together into one?
I feel like what I'm doing should have some neat solution and I don't want to reinvent the wheel, and at the same time I don't want to fall into being too reliant on patterns.
You could create a JoinedCompressionStrategy
class JoinedCompressionStrategy implements CompressionStrategy {
private final CompressionStrategy s0;
private final CompressionStrategy s1;
public JoinedCompressionStrategy(CompressionStrategy s0, CompressionStrategy s1) {
this.s0 = s0;
this.s1 = s1;
}
public File compressFiles(ArrayList<File> files) {
File archive = s0.compressFiles(files);
return s1.compressFiles(Arrays.asList(archive));
}
}
You probably are looking for a decorator pattern implementation instead. The intent of this pattern is to add additional responsibilities dynamically to an object. Tradeoff is that you'll get a explossion of subclasses too.
Example with code:
The common interface.
public interface CompressionStrategy{
File compressFiles(List<File> files);
}
the base compression for all files.
public class CompressionBase implements CompressionStrategy{
#Override
public File compressFiles(List<File> files)) {
//return default compression
}
}
The decorator abstract class
public abstract class AbstractCompressionDecorator implements CompressionStrategy{
private final CompressionStrategy decoratee;
/**
* #param decoratee
*/
public AbstractCompressionDecorator(CompressionStrategy decoratee) {
super();
this.decoratee = decoratee;
}
#Override
public File compressFiles(List<File> files) {
File file = decoratee.compressFiles(files);
return compressFilesToAnotherFormat(file);
}
protected abstract File compressFilesToAnotherFormat(File file);
}
and the decorators concrete classes.
public class TarCompression extends AbstractCompressionDecorator {
public TarCompression (CompressionStrategy compressionStrategy) {
super(compressionStrategy);
}
#Override
protected File compressFilesToAnotherFormat(File file) {
// tar compression logic here;
}
}
Zip compression
public class ZipCompression extends AbstractCompressionDecorator {
public ZipCompression (CompressionStrategy compressionStrategy) {
super(compressionStrategy);
}
#Override
protected File compressFilesToAnotherFormat(File file) {
// zip compression logic here;
}
and a simple Factory to create objects
public final class CompressionFactory {
private CompressionFactory (){}
public static CompressionStrategy create(String extension){
CompressionStrategy compressionStrategy = new CompressionBase();
if(extension.contains("zip")){
compressionStrategy = new ZipCompression(compressionStrategy);
}else if(extension.contains("tar.gzip")){
compressionStrategy = new TarCompression(new GzipCompression(compressionStrategy));
}
return compressionStrategy ;
}
}
then in client code you only have to write this.
CompressionStrategy compressionStrategy = CompressionFactory.create("tar.gzip");
File file = compressionStrategy.compressFiles(files);
public class TgzCompressionStrategy implements CompressionStrategy
{
TarCompressionStrategy tar = new TarCompressionStrategy();
ZipCompressionStrategy zip = new ZipCompressionStrategy();
public File compressFiles(ArrayList<File> files)
{
File archive = tar.compressFiles(files);
archive = zip.compressFiles(archive); // need to handle archive is not array list, but you can do that
return archive;
}
}
I have a Singleton/Factory object that I'd like to write a JUnit test for. The Factory method decides which implementing class to instantiate based upon a classname in a properties file on the classpath. If no properties file is found, or the properties file does not contain the classname key, then the class will instantiate a default implementing class.
Since the factory keeps a static instance of the Singleton to use once it has been instantiated, to be able to test the "failover" logic in the Factory method I would need to run each test method in a different classloader.
Is there any way with JUnit (or with another unit testing package) to do this?
edit: here is some of the Factory code that is in use:
private static MyClass myClassImpl = instantiateMyClass();
private static MyClass instantiateMyClass() {
MyClass newMyClass = null;
String className = null;
try {
Properties props = getProperties();
className = props.getProperty(PROPERTY_CLASSNAME_KEY);
if (className == null) {
log.warn("instantiateMyClass: Property [" + PROPERTY_CLASSNAME_KEY
+ "] not found in properties, using default MyClass class [" + DEFAULT_CLASSNAME + "]");
className = DEFAULT_CLASSNAME;
}
Class MyClassClass = Class.forName(className);
Object MyClassObj = MyClassClass.newInstance();
if (MyClassObj instanceof MyClass) {
newMyClass = (MyClass) MyClassObj;
}
}
catch (...) {
...
}
return newMyClass;
}
private static Properties getProperties() throws IOException {
Properties props = new Properties();
InputStream stream = Thread.currentThread().getContextClassLoader().getResourceAsStream(PROPERTIES_FILENAME);
if (stream != null) {
props.load(stream);
}
else {
log.error("getProperties: could not load properties file [" + PROPERTIES_FILENAME + "] from classpath, file not found");
}
return props;
}
This question might be old but since this was the nearest answer I found when I had this problem I though I'd describe my solution.
Using JUnit 4
Split your tests up so that there is one test method per class (this solution only changes classloaders between classes, not between methods as the parent runner gathers all the methods once per class)
Add the #RunWith(SeparateClassloaderTestRunner.class) annotation to your test classes.
Create the SeparateClassloaderTestRunner to look like this:
public class SeparateClassloaderTestRunner extends BlockJUnit4ClassRunner {
public SeparateClassloaderTestRunner(Class<?> clazz) throws InitializationError {
super(getFromTestClassloader(clazz));
}
private static Class<?> getFromTestClassloader(Class<?> clazz) throws InitializationError {
try {
ClassLoader testClassLoader = new TestClassLoader();
return Class.forName(clazz.getName(), true, testClassLoader);
} catch (ClassNotFoundException e) {
throw new InitializationError(e);
}
}
public static class TestClassLoader extends URLClassLoader {
public TestClassLoader() {
super(((URLClassLoader)getSystemClassLoader()).getURLs());
}
#Override
public Class<?> loadClass(String name) throws ClassNotFoundException {
if (name.startsWith("org.mypackages.")) {
return super.findClass(name);
}
return super.loadClass(name);
}
}
}
Note I had to do this to test code running in a legacy framework which I couldn't change. Given the choice I'd reduce the use of statics and/or put test hooks in to allow the system to be reset. It may not be pretty but it allows me to test an awful lot of code that would be difficult otherwise.
Also this solution breaks anything else that relies on classloading tricks such as Mockito.
When I run into these sort of situations I prefer to use what is a bit of a hack. I might instead expose a protected method such as reinitialize(), then invoke this from the test to effectively set the factory back to its initial state. This method only exists for the test cases, and I document it as such.
It is a bit of a hack, but it's a lot easier than other options and you won't need a 3rd party lib to do it (though if you prefer a cleaner solution, there probably are some kind of 3rd party tools out there you could use).
You can use Reflection to set myClassImpl by calling instantiateMyClass() again. Take a look at this answer to see example patterns for playing around with private methods and variables.
If executing Junit via the Ant task you can set fork=true to execute every class of tests in it's own JVM. Also put each test method in its own class and they will each load and initialise their own version of MyClass. It's extreme but very effective.
Below you can find a sample that does not need a separate JUnit test runner and works also with classloading tricks such as Mockito.
package com.mycompany.app;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import java.net.URLClassLoader;
import org.junit.Test;
public class ApplicationInSeparateClassLoaderTest {
#Test
public void testApplicationInSeparateClassLoader1() throws Exception {
testApplicationInSeparateClassLoader();
}
#Test
public void testApplicationInSeparateClassLoader2() throws Exception {
testApplicationInSeparateClassLoader();
}
private void testApplicationInSeparateClassLoader() throws Exception {
//run application code in separate class loader in order to isolate static state between test runs
Runnable runnable = mock(Runnable.class);
//set up your mock object expectations here, if needed
InterfaceToApplicationDependentCode tester = makeCodeToRunInSeparateClassLoader(
"com.mycompany.app", InterfaceToApplicationDependentCode.class, CodeToRunInApplicationClassLoader.class);
//if you want to try the code without class loader isolation, comment out above line and comment in the line below
//CodeToRunInApplicationClassLoader tester = new CodeToRunInApplicationClassLoaderImpl();
tester.testTheCode(runnable);
verify(runnable).run();
assertEquals("should be one invocation!", 1, tester.getNumOfInvocations());
}
/**
* Create a new class loader for loading application-dependent code and return an instance of that.
*/
#SuppressWarnings("unchecked")
private <I, T> I makeCodeToRunInSeparateClassLoader(
String packageName, Class<I> testCodeInterfaceClass, Class<T> testCodeImplClass) throws Exception {
TestApplicationClassLoader cl = new TestApplicationClassLoader(
packageName, getClass(), testCodeInterfaceClass);
Class<?> testerClass = cl.loadClass(testCodeImplClass.getName());
return (I) testerClass.newInstance();
}
/**
* Bridge interface, implemented by code that should be run in application class loader.
* This interface is loaded by the same class loader as the unit test class, so
* we can call the application-dependent code without need for reflection.
*/
public static interface InterfaceToApplicationDependentCode {
void testTheCode(Runnable run);
int getNumOfInvocations();
}
/**
* Test-specific code to call application-dependent code. This class is loaded by
* the same class loader as the application code.
*/
public static class CodeToRunInApplicationClassLoader implements InterfaceToApplicationDependentCode {
private static int numOfInvocations = 0;
#Override
public void testTheCode(Runnable runnable) {
numOfInvocations++;
runnable.run();
}
#Override
public int getNumOfInvocations() {
return numOfInvocations;
}
}
/**
* Loads application classes in separate class loader from test classes.
*/
private static class TestApplicationClassLoader extends URLClassLoader {
private final String appPackage;
private final String mainTestClassName;
private final String[] testSupportClassNames;
public TestApplicationClassLoader(String appPackage, Class<?> mainTestClass, Class<?>... testSupportClasses) {
super(((URLClassLoader) getSystemClassLoader()).getURLs());
this.appPackage = appPackage;
this.mainTestClassName = mainTestClass.getName();
this.testSupportClassNames = convertClassesToStrings(testSupportClasses);
}
private String[] convertClassesToStrings(Class<?>[] classes) {
String[] results = new String[classes.length];
for (int i = 0; i < classes.length; i++) {
results[i] = classes[i].getName();
}
return results;
}
#Override
public Class<?> loadClass(String className) throws ClassNotFoundException {
if (isApplicationClass(className)) {
//look for class only in local class loader
return super.findClass(className);
}
//look for class in parent class loader first and only then in local class loader
return super.loadClass(className);
}
private boolean isApplicationClass(String className) {
if (mainTestClassName.equals(className)) {
return false;
}
for (int i = 0; i < testSupportClassNames.length; i++) {
if (testSupportClassNames[i].equals(className)) {
return false;
}
}
return className.startsWith(appPackage);
}
}
}