Untestable part of Code - java

I have a class which is not instantiated and is composed of static methods only. I managed to cover all the parts of the getProperty() except the catch(IOException e) part, however the code seems to be unreachable.
public class ResourceUtils
{
private static final String IOEXCEPTION_ERROR_MESSAGE = "ERROR: Problem reading StringBundles.properties";
private static final String PATH_STRING_BUNDLE = "com/qn/config/StringBundles.properties";
public static String getProperty( String key )
{
Properties property = new Properties();
try
{
property.load( ResourceUtils.class.getClassLoader().getResourceAsStream( PATH_STRING_BUNDLE ) );
}
catch( IOException e )
{
System.err.println( IOEXCEPTION_ERROR_MESSAGE );
e.printStackTrace();
return null;
}
return property.getProperty( key );
}
I wanted to test the scenario where in the PATH_STRING_BUNDLE would be invalid and it wall pass through the catch(IOException e). However the PATH_STRING_BUNDLE has a final modifier. Can you suggest a way to test this or is testing this part pretty useless or maybe the design of the class have problems.

In your Unit test, temporarily rename the file com/qn/config/StringBundles.properties, and then run the code. When the test is complete, rename it back.

In this situations I usually introduce use this immediate solution (there's also a cleaner solution but it requires wider refactoring): I create a new overload of the method, which takes one extra parameter, and uses this parameter in place of the PATH_STRING_BUNDLE constant. Then I change the original method such that it simply passes PATH_STRING_BUNDLE to the new overload. Here's how the code looks like:
import java.io.IOException;
import java.util.Properties;
public class ResourceUtils
{
private static final String IOEXCEPTION_ERROR_MESSAGE = "ERROR: Problem reading StringBundles.properties";
private static final String PATH_STRING_BUNDLE = "com/qn/config/StringBundles.properties";
public static String getProperty(String key) {
return getProperty(key, PATH_STRING_BUNDLE);
}
static String getProperty(String key, String bundlePath)
{
Properties property = new Properties();
try
{
property.load(ResourceUtils.class.getClassLoader().getResourceAsStream(bundlePath));
}
catch( IOException e )
{
System.err.println( IOEXCEPTION_ERROR_MESSAGE );
e.printStackTrace();
return null;
}
return property.getProperty( key );
}
}
Now you can test the scenario where the bundle path is broken simply by calling the new overload passing in whatever value you want for the second parameter.

Related

How to get configuration value for static value in Quarkus

I am rewriting exceptions from an old system and everything was working, but I needed make BAD_REQUEST configurable.
private static final String BAD_REQUEST = "BDRQ";
I tried to just put ConfigProperty, but it doesn't work.
import javax.ws.rs.core.Response.Status;
import org.eclipse.microprofile.config.inject.ConfigProperty;
public class SXClientException extends RuntimeException {
#ConfigProperty(name = "greeting.error", defaultValue = "BDRQ")
public String BAD_REQUEST;
private final RuntimeException runtimeException;
public SXClientException(RuntimeException e) {
super(e);
this.runtimeException = e;
}
public Status getStatus() {
if (BAD_REQUEST.equals(runtimeException.getMessage())) {
return Status.BAD_REQUEST;
}
return Status.INTERNAL_SERVER_ERROR;
}
// ...
}
It probably doesn't work since I make them without any CDI.
catch (LegacyOMException e) {
throw new SXClientException(e);
}
I would prefer to avoid creating another bean (and passing the value) just to compare one String. Any idea how can I read a configuration value for a static-ish value?
you can use org.eclipse.microprofile.config.ConfigProvider.
Works for both static and non static members.
public static final String BAD_REQUEST = ConfigProvider.getConfig().getValue("greeting.error",String.class);
public final String BAD_REQUEST = ConfigProvider.getConfig().getValue("greeting.error",String.class);
use follow method:
Properties properties = new Properties();
InputStream inputStream = this.getClass().getResourceAsStream("/menu.properties");
properties.load(inputStream );
System.out.println(properties.getProperty("a"));

How to test function which calls another void function from it with static value as argument using mockito

I have a class A as
Class A{
private static final String ANON_DIR = "/webapps/worldlingo/data/anonymizer/";
private static final String NO_ANON = "noanonymize";
public String first(String text, String srclang, Map dictTokens) {
Set<String> noAnonymize = new HashSet<String>();
second(noAnonymize,ANON_DIR + NO_ANON, "tmpLang","name");
String value;
if(noAnonymize.contains("test")){
value = word;
}
else {
value = "test";
}
return value;
}
where ANON_DIR and NO_ANON is static final value. This class has function first and function second .The first function has a calling method in it which calls second function. The second function is void function which takes static fields as parameter.
Second function is just the file read function with the path provided as
private void second (Set<String> hashSet, String path, String lang , String type) {
FileReader fr = null;
BufferedReader br = null;
try {
fr = new FileReader(path);
br = new BufferedReader(fr);
String Line;
while ((Line = br.readLine()) != null) {
hashSet.add(Line);
}
} catch (IOException e) {
log.error("Anonymizer: Unable to load file.", e);
} finally {
try {
if (fr != null) {
fr.close();
}
if (br != null) {
br.close();
}
} catch (IOException e) {
log.error("Anonymizer : An error occured while closing a resource.", e);
}
}
}
}
Now I am trying to test the function first using mockito. I am trying to change the static parameter and send those changed static parameter as
public void testfirst() throws Exception {
A anon = new A();
Field ANON_DIR = A.class.getDeclaredField("ANON_DIR");
ANON_DIR.setAccessible(true);
//java relection to change private static final field
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(ANON_DIR, ANON_DIR.getModifiers() & ~Modifier.FINAL);
ANON_DIR.set(null,"test");
Field NO_ANON = A.class.getDeclaredField("NO_ANON");
NO_ANON.setAccessible(true);
Field modifiersField1 = Field.class.getDeclaredField("modifiers");
modifiersField1.setAccessible(true);
modifiersField1.setInt(NO_ANON, NO_ANON.getModifiers() & ~Modifier.FINAL);
NO_ANON.set(null,"/noanonymize");
Method anonymizeNames = anon.getClass().getDeclaredMethod("first", String.class, String.class , Map.class);
String srcLang = "MSFT_EN";
Map mapTokens = new HashMap();
String result = (String) anonymizeNames.invoke(anon,"I am David",srcLang,mapTokens);
}
PROBLEM:
Here I could change the private final static field ANON_DIR and NO_ANON using java reflection but the changed field are not send to the second function. The second function called from first function takes the original value instead of changed value. i.e when the second is called ANON_DIR has
"/webapps/worldlingo/data/anonymizer/" value instead of "test".
Since I changed the value of ANON_DIR to "test" I want the same "test" value to be passed to the second function. How can I acheive this for testing for void second method.
The problem here is the violation of the Separation of concerns principle.
Your code under test (cut) does too much and thus you have a hard time to find seams to replace dependencies.
Also there is a misunderstanding of the aim of unittests. You don't test code, you test public observable behavior which is any return value and communication with dependencies (but not necessarily public methods).
So my suggestion is to move method second() to a new class of its own. The cut gets an instance of this new class passed in as constructor parameter.
Then it is easy to replace the real dependency with a mock of that new class in your test.
On the other hand you could simple surrender to your bad design by using PowerMock...

How to initialise a static final class member of type ObjectName?

The following code does not compile ("variable name might not have been initialized"):
import javax.management.*;
public class Main {
public final static ObjectName name;
static {
try {
name = new ObjectName("abc");
} catch (final Exception e) {
System.exit(1);
}
}
}
However, the following code does not compile either ("variable name might already have been assigned"):
import javax.management.*;
public class Main {
public final static ObjectName name;
static {
try {
name = new ObjectName("abc");
} catch (final Exception e) {
name = null;
System.exit(1);
}
}
}
I do not think the compiler is right about the either case, but anyways how are we supposed to initialize a static final ObjectName?
The first line of advice is don't call System.exit(). It causes the application to suddenly quit, without normal cleanup.
If you absolutely must exit the application at that precise point, then your workaround is to add
throw e;
after your System.exit() call.
If you're curious about the compiler error, you may be interested to read about it in this question.
The compiler expects that, in all possible branches of execution within your static initializer block, that ObjectName is assigned a value.
In
static {
try {
name = new ObjectName("abc");
} catch (final Exception e) {
System.exit(1);
}
}
Since ObjectName is not assigned a value in the catch-block, and since no exception is thrown, the compiler does not allow it.
If there were an exception thrown in the catch block, it would be acceptable.
An alternative method to implementing static initializer blocks, which I prefer, is where the block is a simple call to a private static function:
static {
init();
}
private static init() {
//do stuff
}
Just use a private static method instead of the static initializer:
private static final ObjectName name = initObjectName();
private static ObjectName initObjectName() {
try {
return new ObjectName("abc");
} catch (MalformedObjectNameException e) {
return null;
}
}

How to Load Values for Java Enum Elements from A File

I have a Java Enum:
public enum CodeType {
BRONZE("00001BP", "BAP"),
SILVER("00002SL", "SAP"),
GOLD("00003GL", "GAP"),
MOBILE("00004MB", "TCM"),
SOCIAL("00005SM", "ASM"),
WEB_PRESENCE("00006WP", "GLO"),
EMAIL_MARKETING("00007EM", "PEM"),
CUSTOM_DIAMOND("00008CD", "PCS"),
CONSUMER_PORTAL("00009CP", "CPS");
private String code;
private String key;
CodeType(String code, String key) {
this.code = code;
this.key = key;
}
...
}
As you see, I have nine elements and each has two values. My question is How can I load values for those elements from a file like properties or xml? I mean:
BRONZE(isLoadedFromFile, isLoadedFromFile),
...
CONSUMER_PORTAL(isLoadedFromFile, isLoadedFromFile);
Thanks so much.
Try something like this..
public enum EnumTest {
BRONZE, SILVER;
public String getProperty(String keyOrCode) {
Properties prop = new Properties();
try {
prop.load(new FileInputStream("E:\\EnumMapper.properties"));
} catch (Exception e) {
e.printStackTrace();
}
return prop.getProperty(this.name() + "." + keyOrCode);
}
public String getCode() {
return getProperty("CODE");
}
public String getKey() {
return getProperty("KEY");
}
public static void main(String[] args) {
System.out.println(EnumTest.BRONZE.getCode());
System.out.println(EnumTest.BRONZE.getKey());
}
}
where the EnumMapper.properties contains
BRONZE.CODE=00001BP
BRONZE.KEY=BAP
SILVER.CODE=00002SL
SILVER.KEY=SAP
Just wanted to share some possibilities..
If I understand your question correctly, you would need to do so in the constructor (which is misnamed in your example).
The hard-coded defaults you show would serve as the defaults, but in the constructor you would check/load some properties file and override them.
In general though, this smells of an odd/bad design. You would need to hard-code that properties file / resource in the enum. You're also dynamically loading what is meant to be something that represents a constant value.
It seems like really you should be using your own class to hold these values.
One option is to generate a static map based on the resource file within the enum class, mapping from enum values to the data in the file. The map can then be used for the getter.
For instance with a resource file formatted like this:
A=red
B=blue
C=yellow
it can be initialized like this:
public enum MyEnum {
A, B, C;
public String getFoo() {
return enumFooValuesFromResourceFile.get(this);
}
private static final Map<MyEnum, String> enumFooValuesFromResourceFile;
static {
Map<MyEnum, String> temp = Collections.emptyMap();
try {
String data = new String(MyEnum.class.getResourceAsStream("resourcepath").readAllBytes());
temp = Arrays.stream(data.split("\n"))
.map(line -> line.split("="))
.collect(Collectors.<String[], MyEnum, String>toMap(
key_val -> MyEnum.valueOf(key_val[0]),
key_val -> key_val[1]));
} catch (IOException iE) {
// helpful message.
} finally { enumFooValuesFromResourceFile = temp; }
}
}
A nicer option, I think, is to use a static String for the resource file data, and store the values directly on the enum items during initialization. During enum initialization, you cannot access a static property of the enum, so it must either be outside it, or in an inner class using the Initialization-on-demand holder idiom (credit to) which is neat, because it's lazy and not loaded if the enum is never accessed.
(I found I can set the (non-final) String to null at the end of the enum declaration, freeing that memory.)
public enum MyEnum {
A, B, C;
public String getFoo() { return foo; }
final String foo;
MyEnum() {
foo = getFooValue();
}
private String getFooValue() {
return Arrays.stream(ResourceHolder.resourceFileString.split("\n"))
.filter(str -> str.startsWith(this.name() + '='))
.findFirst()
.map(str -> str.replaceAll("^" + this.name() + '=', ""))
.orElseThrow(() ->
new IllegalArgumentException(this.name() + " not found in resourcefile."));
}
// Release resources (string) from memory after enum initialization.
static {ResourceHolder.resourceFileString = null;}
private static class ResourceHolder {
// Lazily initialized if/when MyEnum is accessed.
// Cleared after initialization.
private static String resourceFileString;
static {
try {
InputStream lResource =
Objects.requireNonNull(MyEnum.class.getResourceAsStream("resourcepath"));
resourceFileString = new String(lResource.readAllBytes());
} catch (IOException iE) {
// helpful message.
iE.printStackTrace();
}
}
}
}

How can I find all the methods that call a given method in Java?

I need to get a list of all caller methods for a method of interest for me in Java. Is there a tool that can help me with this?
Edit: I forgot to mention that I need to do this from a program. I'm usig Java Pathfinder and I want to run it an all the methods that call my method of interest.
For analyzing bytecode, I would recommend ASM. Given a list of Classes to analyze, a visitor can be made which finds the method calls you're interested in. One implementation which analyses classes in a jar file is below.
Note that ASM uses internalNames with '/' instead of '.' as a separator. Specify the target method as a standard declaration without modifiers.
For example, to list methods that could be calling System.out.println("foo") in the java runtime jar:
java -cp "classes;asm-3.1.jar;asm-commons-3.1.jar" App \
c:/java/jdk/jre/lib/rt.jar \
java/io/PrintStream "void println(String)"
Edit: source and line numbers added: Note that this only indicates the last target method invocation per calling method - the original q only wanted to know which methods. I leave it as an exercise for the reader to show line numbers of the calling method declaration, or the line numbers of every target invocation, depending on what you're actually after. :)
results in:
LogSupport.java:44 com/sun/activation/registries/LogSupport log (Ljava/lang/String;)V
LogSupport.java:50 com/sun/activation/registries/LogSupport log (Ljava/lang/String;Ljava/lang/Throwable;)V
...
Throwable.java:498 java/lang/Throwable printStackTraceAsCause (Ljava/io/PrintStream;[Ljava/lang/StackTraceElement;)V
--
885 methods invoke java/io/PrintStream println (Ljava/lang/String;)V
source:
public class App {
private String targetClass;
private Method targetMethod;
private AppClassVisitor cv;
private ArrayList<Callee> callees = new ArrayList<Callee>();
private static class Callee {
String className;
String methodName;
String methodDesc;
String source;
int line;
public Callee(String cName, String mName, String mDesc, String src, int ln) {
className = cName; methodName = mName; methodDesc = mDesc; source = src; line = ln;
}
}
private class AppMethodVisitor extends MethodAdapter {
boolean callsTarget;
int line;
public AppMethodVisitor() { super(new EmptyVisitor()); }
public void visitMethodInsn(int opcode, String owner, String name, String desc) {
if (owner.equals(targetClass)
&& name.equals(targetMethod.getName())
&& desc.equals(targetMethod.getDescriptor())) {
callsTarget = true;
}
}
public void visitCode() {
callsTarget = false;
}
public void visitLineNumber(int line, Label start) {
this.line = line;
}
public void visitEnd() {
if (callsTarget)
callees.add(new Callee(cv.className, cv.methodName, cv.methodDesc,
cv.source, line));
}
}
private class AppClassVisitor extends ClassAdapter {
private AppMethodVisitor mv = new AppMethodVisitor();
public String source;
public String className;
public String methodName;
public String methodDesc;
public AppClassVisitor() { super(new EmptyVisitor()); }
public void visit(int version, int access, String name,
String signature, String superName, String[] interfaces) {
className = name;
}
public void visitSource(String source, String debug) {
this.source = source;
}
public MethodVisitor visitMethod(int access, String name,
String desc, String signature,
String[] exceptions) {
methodName = name;
methodDesc = desc;
return mv;
}
}
public void findCallingMethodsInJar(String jarPath, String targetClass,
String targetMethodDeclaration) throws Exception {
this.targetClass = targetClass;
this.targetMethod = Method.getMethod(targetMethodDeclaration);
this.cv = new AppClassVisitor();
JarFile jarFile = new JarFile(jarPath);
Enumeration<JarEntry> entries = jarFile.entries();
while (entries.hasMoreElements()) {
JarEntry entry = entries.nextElement();
if (entry.getName().endsWith(".class")) {
InputStream stream = new BufferedInputStream(jarFile.getInputStream(entry), 1024);
ClassReader reader = new ClassReader(stream);
reader.accept(cv, 0);
stream.close();
}
}
}
public static void main( String[] args ) {
try {
App app = new App();
app.findCallingMethodsInJar(args[0], args[1], args[2]);
for (Callee c : app.callees) {
System.out.println(c.source+":"+c.line+" "+c.className+" "+c.methodName+" "+c.methodDesc);
}
System.out.println("--\n"+app.callees.size()+" methods invoke "+
app.targetClass+" "+
app.targetMethod.getName()+" "+app.targetMethod.getDescriptor());
} catch(Exception x) {
x.printStackTrace();
}
}
}
Edit: the original question was edited to indicate a runtime solution was needed - this answer was given before that edit and only indicates how to do it during development.
If you are using Eclipse you can right click the method and choose "Open call hierarchy" to get this information.
Updated after reading comments: Other IDEs support this as well in a similar fashion (at least Netbeans and IntelliJ do)
Annotate the method with #Deprecated ( or tag it with #deprecated ), turn on deprecation warnings, run your compile and see which warnings get triggered.
The run your compile bit can be done either by invoking an external ant process or by using the Java 6 compiler API.
right click on method
Go to references and (depending on your requirement)
choose workspace/project/Hierarchy.
This pops up a panel that shows all references to this functions. Eclipse FTW !
In eclipse, highlight the method name and then Ctrl+Shift+G
There isn't a way to do this (programmatically) via the Java reflection libraries - you can't ask a java.lang.reflect.Method "which methods do you call?"
That leaves two other options I can think of:
Static analysis of the source code. I'm sure this is what the Eclipse Java toolset does - you could look at the Eclipse source behind the JDT, and find what it does when you ask Eclipse to "Find References" to a method.
Bytecode analysis. You could inspect the bytecode for calls to the method. I'm not sure what libraries or examples are out there to help with this - but I can't imagine that something doesn't exist.
Yes, most modern IDE:s will let you either search for usages of a method or variable. Alternatively, you could use a debugger and set a trace point on the method entry, printing a stack trace or whatever every time the method is invoked.
Finally, you could use some simple shell util to just grep for the method, such as
find . -name '*.java' -exec grep -H methodName {} ;
The only method that will let you find invokations made through some reflection method, though, would be using the debugger.
I made a small example using #Chadwick's one. It's a test that assesses if calls to getDatabaseEngine() are made by methods that implement #Transaction.
/**
* Ensures that methods that call {#link DatabaseProvider#getDatabaseEngine()}
* implement the {#link #Transaction} annotation.
*
* #throws Exception If something occurs while testing.
*/
#Test
public void ensure() throws Exception {
final Method method = Method.getMethod(
DatabaseEngine.class.getCanonicalName() + " getDatabaseEngine()");
final ArrayList<java.lang.reflect.Method> faultyMethods = Lists.newArrayList();
for (Path p : getAllClasses()) {
try (InputStream stream = new BufferedInputStream(Files.newInputStream(p))) {
ClassReader reader = new ClassReader(stream);
reader.accept(new ClassAdapter(new EmptyVisitor()) {
#Override
public MethodVisitor visitMethod(final int access, final String name, final String desc, final String signature, final String[] exceptions) {
return new MethodAdapter(new EmptyVisitor()) {
#Override
public void visitMethodInsn(int opcode, String owner, String nameCode, String descCode) {
try {
final Class<?> klass = Class.forName(Type.getObjectType(owner).getClassName());
if (DatabaseProvider.class.isAssignableFrom(klass) &&
nameCode.equals(method.getName()) &&
descCode.equals(method.getDescriptor())) {
final java.lang.reflect.Method method = klass.getDeclaredMethod(name,
getParameters(desc).toArray(new Class[]{}));
for (Annotation annotation : method.getDeclaredAnnotations()) {
if (annotation.annotationType().equals(Transaction.class)) {
return;
}
}
faultyMethods.add(method);
}
} catch (Exception e) {
Throwables.propagate(e);
}
}
};
}
}, 0);
}
}
if (!faultyMethods.isEmpty()) {
fail("\n\nThe following methods must implement #Transaction because they're calling getDatabaseEngine().\n\n" + Joiner.on("\n").join
(faultyMethods) + "\n\n");
}
}
/**
* Gets all the classes from target.
*
* #return The list of classes.
* #throws IOException If something occurs while collecting those classes.
*/
private List<Path> getAllClasses() throws IOException {
final ImmutableList.Builder<Path> builder = new ImmutableList.Builder<>();
Files.walkFileTree(Paths.get("target", "classes"), new SimpleFileVisitor<Path>() {
#Override
public FileVisitResult visitFile(final Path file, final BasicFileAttributes attrs) throws IOException {
if (file.getFileName().toString().endsWith(".class")) {
builder.add(file);
}
return FileVisitResult.CONTINUE;
}
});
return builder.build();
}
/**
* Gets the list of parameters given the description.
*
* #param desc The method description.
* #return The list of parameters.
* #throws Exception If something occurs getting the parameters.
*/
private List<Class<?>> getParameters(String desc) throws Exception {
ImmutableList.Builder<Class<?>> obj = new ImmutableList.Builder<>();
for (Type type : Type.getArgumentTypes(desc)) {
obj.add(ClassUtils.getClass(type.getClassName()));
}
return obj.build();
}
1)In eclipse it is ->right click on the method and select open call hierarchy or CLT+ALT+H
2)In jdeveloper it is -> right click on the method and select calls or ALT+SHIFT+H
The closest that I could find was the method described in this StackOverflow questions selected answer.check this out
You can do this with something in your IDE such as "Find Usages" (which is what it is called in Netbeans and JDeveloper). A couple of things to note:
If your method implements a method from an interface or base class, you can only know that your method is POSSIBLY called.
A lot of Java frameworks use Reflection to call your method (IE Spring, Hibernate, JSF, etc), so be careful of that.
On the same note, your method could be called by some framework, reflectively or not, so again be careful.

Categories

Resources