Using java reflection - java

I am trying to invoke a private method belonging to one class from another class using java reflection. Both these classes belong to different packages. Code sample is as below. But everytime I run the getDeclaredMethod it returns with NoSuchMethodException. How do I invoke the getCacheKey method from my class?
Thanks,
Class A
package com.abc;
public class TicketHelper
{
static String getCacheKey(String ticketString, Ticket ticket) throws TicketException, UnsupportedEncodingException, NoSuchAlgorithmException {
...
}
}
Class B
package com.def;
...
private Method method = null;
public class TicketHelper
{
...
try {
method = TicketHelper.class.getDeclaredMethod("getCacheKey", new Class[] {String.class, Ticket.class});
} catch (SecurityException e1) {
setTrace("Security exception2 " + e1.getMessage());
} catch (NoSuchMethodException e1) {
setTrace("No such method exception2 " + e1.getMessage());
}
method.setAccessible(true);
m_cacheKey = method.invoke(null, new Object[] {ticketString, ticket});
}

Is the class in com.def also called TicketHelper? In that case you need to qualify as com.abc.TicketHelper
EDIT
There are several compilation errors in the code you posted. Always try to come up with a short example that reproduces the problem; in most cases you will see you error in that process. The following works for me. It is same package, but that should not matter:
public class TicketHelperUser
{
public static void main(String[] args) throws Exception
{
for (java.lang.reflect.Method m : TicketHelper.class.getDeclaredMethods())
{
System.out.println(m);
}
java.lang.reflect.Method method = TicketHelper.class.getDeclaredMethod("getCacheKey", String.class, Ticket.class);
method.setAccessible(true);
method.invoke(null, new Object[] {"", new Ticket()});
}
}
public class TicketHelper
{
static String getCacheKey(String ticketString, Ticket ticket)
{
return "cacheKey";
}
}
public class Ticket {}

Not a solution but a test to identify the problem: get all declared methods and verify, that the getCacheKey is visible/present:
Method[] methods = TicketHelper.class.getDeclaredMethods();
for (Method method:methods) {
if (method.getName().equals("getCacheKey")) {
System.out.println(method); // <-- breakpoint and inspect the method object
}
}

Take a look at:
http://www.wikijava.org/wiki/Class_and_static_Method_Reflection_example
they are using getMethod instead getDeclaredMethod

Related

Better way to continue after exceptions in java

Assuming I have to read from a file, and then construct a java object out of it.
PersonData p = new PersonData();
p.setName(readTokenAsString());
p.setAge(AgeConverter.createFromDateOfBirth(readTokenAsString())); // this throws a checked exception if the date of birth is mal-formed.
//... a list of methods that throws exception as AgeConverter
Behavior I want: If one attribute has problem, just ignore it and keep process other attributes.
Solution I can think of:
try {
p.setAge1(...);
} catch (Exception e) {
//log and ignore
}
try {
p.setAge2(...);
} catch (Exception e) {
//log and ignore
}
//repeat for each attribute
Question:
Is there better way to do this to avoid repetition? Functional style maybe?
a) What's the best approach if I cannot modify PersonData class.
b) What's the best approach if I can rewrite PersonData class.
Given your current declaration, I would do it as follows.
Define a #FunctionalInterface to which you can pass your I/O logic:
#FunctionalInterface
public interface CheckedSupplier<T> {
T getValue() throws Exception;
}
Define an utility method that consumes the #FunctionaInterface:
public static final <T> T getValueWithDefault(CheckedSupplier<T> supplier, T defaultValue) {
try {
return supplier.getValue();
} catch (Exception e){
return defaultValue;
}
}
Use the utility method as follows:
PersonData p = new PersonData();
p.setName(getValueWithDefault(() -> readTokenAsString(), "default"));
p.setAge(getValueWithDefault(() -> AgeConverter.createFromDateOfBirth(readTokenAsString()), 0));
This should do the trick regardless of weather you want modify the PersonData class or not.
If you use Java 8 you can do something like this. Create your own functional interface with one method that throws Exception
public interface MyConsumer<T> {
public void process(T t) throws Exception;
}
And create a static method to use that interface
public static <T> void setAndLogException(T value, MyConsumer<T> consumer) {
try {
consumer.process(value);
} catch (Exception e) {
// log exception
}
}
And then using it like setAndLogException(AgeConverter.createFromDateOfBirth(readTokenAsString()), p::setAge);
You can also use solution provided by this: https://stackoverflow.com/a/28659553/6648303
This solution won't complain at compile phase about checked Exceptions.
It would be something like this:
public static void ignoringExc(RunnableExc r) {
try { r.run(); } catch (Exception e) { }
}
#FunctionalInterface public interface RunnableExc { void run() throws Exception; }
and then:
PersonData p = new PersonData();
ignoringExc(() -> p.setName(readTokenAsString()));
...

EasyMock still goes into implementation of a method mocked with addMockedMethod

I am trying to write a unit-test in Java. Due to the structure of Java class, I have to come up with a way in which whenever a constructor of a class is called, a mocked object of that class is created. I want to mock 2 methods of that class.
CallToBeMocked mockCallToBeMocked = EasyMock.createMockBuilder(CallToBeMocked.class)
.withConstructor(ArgumentA.class, ArgumentB.class, ArgumentC.class)
.withArgs(mockArgumentA, mockArgumentB, mockArgumentC)
.addMockedMethod("isProxied", ArgumentA.class)
.addMockedMethod("remoteCall", String.class, ArgumentA.class, Object.class)
.createMock();
EasyMock.expect(mockCallToBeMocked.isProxied(mockArgumentA)).andReturn(false);
EasyMock.expect(mockCallToBeMocked.remoteCall("ip-address", mockArgumentA, null)).andThrow(new Exception()).times(3);
The problem is that although I have clearly specified that isProxied and remoteCall methods have to be mocked and I have given appropriate expectations for those methods, it still starts going into the actual implementations of these methods.
It should perfectly work. So something else is going on. Here is a working example based on your code. What's different from your actual implementation?
public class PartialTest {
public interface ArgumentA { }
public interface ArgumentB { }
public interface ArgumentC { }
public static class CallToBeMocked {
public CallToBeMocked(ArgumentA a, ArgumentB b, ArgumentC c) {
}
public boolean isProxied(ArgumentA a) {
return true;
}
public int remoteCall(String ip, ArgumentA a, Object any) throws Exception {
return 0;
}
}
#Test
public void test() throws Exception {
ArgumentA mockArgumentA = createNiceMock(ArgumentA.class);
ArgumentB mockArgumentB = createNiceMock(ArgumentB.class);
ArgumentC mockArgumentC = createNiceMock(ArgumentC.class);
CallToBeMocked mockCallToBeMocked = createMockBuilder(CallToBeMocked.class)
.withConstructor(ArgumentA.class, ArgumentB.class, ArgumentC.class)
.withArgs(mockArgumentA, mockArgumentB, mockArgumentC)
.addMockedMethod("isProxied", ArgumentA.class)
.addMockedMethod("remoteCall", String.class, ArgumentA.class, Object.class)
.createMock();
expect(mockCallToBeMocked.isProxied(mockArgumentA)).andReturn(false);
expect(mockCallToBeMocked.remoteCall("ip-address", mockArgumentA, null)).andThrow(new Exception()).times(3);
replay(mockCallToBeMocked);
assertFalse(mockCallToBeMocked.isProxied(mockArgumentA));
try {
mockCallToBeMocked.remoteCall("ip-address", mockArgumentA, null);
fail("Should throw");
} catch (Exception e) { }
try {
mockCallToBeMocked.remoteCall("ip-address", mockArgumentA, null);
fail("Should throw");
} catch (Exception e) { }
try {
mockCallToBeMocked.remoteCall("ip-address", mockArgumentA, null);
fail("Should throw");
} catch (Exception e) { }
verify(mockCallToBeMocked);
}
}
If we aren't tied to EasyMock, here's a way in which the same functionality can be achieved using Mockito.
import static org.mockito.Mockito.verify;
import org.mockito.Mockito;
....
ClassToBeMocked myMock = Mockito.mock(ClassToBeMocked.class);
Mockito
.when(myMock.isProxied(any(ArgumentA.class)))
.thenReturn(false);
Mockito
.when(myMock.remoteCall(any(String.class), any(ArgumentA.class), any(Object.class)))
.thenThrow(new Exception("monkeys"));
<USE ``myMock``>
verify(myMock, times(1)).isProxied(mockArgumentA);
verify(myMock, times(3)).remoteCall("ip-address", mockArgumentA, null);

Java - How to test exception which never will occur?

I have Utils class with method which throws exception when given data are incorrect.
I have also Service which uses this method, but the data are always generated in way that they will be correct during call. Data are generated by another utils class.
I understand that I should throw this exception from Utils class - but I can't throw it from Service - so I have to catch it.
How can I test this, simulate this exception?
All actions on this data are in private methods.
I want to avoid PowerMock, because I heard that it's a sign of bad design.
So the question is, how to implement this in good design?
From your description it looks like this:
class Service {
public void someMethod() {
Data data = AnotherUtils.getData();
try {
Utils.method(data); // exception never thrown
} catch(Exception e) {
// how to test this branch?
}
}
}
The goal would be something like this:
interface DataProvider {
Data getData();
}
interface DataConsumer {
void method(Data data);
}
class Service {
private final DataProvider dataProvider;
private final DataConsumer dataConsumer;
public Service(DataProvider dataProvider, DataConsumer dataConsumer) {...}
public void someMethod() {
Data d = dataProvider.getData();
try {
dataConsumer.method(data);
} catch(Exception e) {
}
}
}
This technique is called dependency injection.
Then, when testing, you can simply provide a mock implementation for this DataProvider interface that does return faulty data:
#Test(expected=Exception.class)
public void myTest() {
DataProvider badDataProvider = () -> new BadData(); // Returns faulty data
Service service = new Service(badDataProvider, Utils.getConsumer());
service.someMethod(); // boom!
}
For the non-testing code, you could simply wrap the utils classes you already have in these interfaces:
class AnotherUtils {
public static Data getData() {...}
public static DataProvider getProvider() {
return AnotherUtils::getData;
}
}
...
Service service = new Service(AnotherUtils.getProvider(), Utils.getConsumer());
Here is an approach where you want to introduce Dependency Injection, but for whatever reason you don't want to change legacy code.
Say you have some static utility method like so:
class Utils{
public static Something aMethod(SomethingElse input) throws AnException{
if(input.isValid())
return input.toSomething();
throw new AnException("yadda yadda");
}
}
And you have a class that uses that utility method. You can still inject it with a FunctionalInterface.
#FunctionalInterface
interface FunctionThrowsAnException<K,V> {
V apply(K input) throws AnException;
}
class Service {
private final FunctionThrowsAnException<SomethingElse,Something> func;
Service(FunctionThrowsAnException<SomethingElse,Something> func){
this.func = func;
}
Something aMethod(SomethingElse input){
try{
return func.apply(input);
}catch(AnException ex){
LOGGER.error(ex);
}
}
}
Then use it like this:
new Service(Utils::aMethod).aMethod(input);
To test it:
new Service(x -> { throw new AnException("HA HA"); }).aMethod(input);

How to set object that is being refereed in private inner class while creating Junit?

I have 2 java classes.
1) class1.java
public class class1
{
private class ParameterVariable
{
class2 c1;
String s;
ParameterVariable(String s)
{
this.s =s;
}
}
public void methodToTest(String s)
{
try
{
ParameterVariable pv = new ParameterVariable(s)
if(StringUtils.isNotEmpty(pv.c1.getPartNo()))
{
// Some Code
}
}
finally
{
// Some code
}
}
}
2) class2.java
public class class2
{
// pojo class
String partNo;
public String getPartNo()
{
return partNo;
}
public void setPartNo(String partNo)
{
this.partNo = partNo;
}
}
Now I want to create a Junit test case for my method. I am not able to get runtime value for class2 object.
Here is my work
private class1 = null;
protected Object createParamterVariableObject ( String s ) throws ClassNotFoundException, InstantiationException,
IllegalAccessException, InvocationTargetException,
NoSuchMethodException, SecurityException
{
Class clazz = Whitebox.getInnerClassType(class1.class, "ParameterVariable");
Constructor constructorForParameterVariable = clazz.getConstructor(String.java)
Object parameterVariableObject = constructorForParameterVariable.newInstance(String.java)
return parameterVariableObject;
}
#Test
public void junitTestCase() throws Exception
{
String s = "Sample";
Class clazz = null;
Object parameterVariableObject = null;
class2 cls2Object = new clsObject;
try
{
parameterVariableObject = createParamterVariableObject(s);
clazz = Whitebox.getInnerClassType(SupersedeImpl.class, "ParameterVariable");
}
catch (Exception e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
class2 c2Object = new class2();
c2Object.setPartNo("NEW_PART_NO");
Field C1Field = (Field) parameterVariableObject.getClass().getDeclaredField("c1");
C1Field.set(parameterVariableObject, C1Field);
PowerMockito.whenNew(clazz).withArguments(s).thenReturn(parameterVariableObject);
class1 = PowerMockito.spy(class1);
class1.methodToTest(s);
// some assertion
}
I want to set some mocking value of part no that is object of class2.
Because my method is based on it.
I am getting null using these code. Can you please help me?
You can try by mocking the object class2 c1,
in your code there must be setter method that is injecting the object.
You can use that in you JUnit test case to return the mock object.
i.e. via doReturn().. when()..
After that you will get the mocked object in your code.
you can use when().. then() for other stuff.
My suggestion: make your life easier:
Change that inner class to a normal class
Create a factory that returns instances of that class
And then use dependency injection to give such a factory to your class under test. And use any ordinary mocking framework to create those objects.
Done. And not only do you avoid all those issues that complicate mocking in your version; you also end up with code that is less tightly coupled.

Get custom method annotation value from junit test

I have a junit test where I'd like to use an annotation on methods to define test settings.
I have a super class of the test class where I have abstracted some processing and where I'd like to read the method annotation values.
I have seen examples of reading method annotations by looping over a class. I'm not sure this will work for what I need. How do I find which test method was called and then read those specific annotation values (TrialMethod.name)?
public class MyUTest extends Processor{
#Test
#TrialMethod(name = "methodToBeTested")
public void testMethod() throws Exception {
//assert stuff
}
}
public class Processor extends TestCase{
private TrialMethodModel trialMethodModel = new TrialMethodModel();
private void setMethodNameByAnnotation() {
Class<?> clazz = this.getClass();
Class<TrialMethod> trialMethodClass = TrialMethod.class;
for (Method method : clazz.getDeclaredMethods()){
if (method.isAnnotationPresent(trialMethodClass)){
trialMethodModel.setName(method.getAnnotation(trialMethodClass).name());
}
}
}
}
#Documented
#Target(ElementType.METHOD)
#Retention(value=RetentionPolicy.RUNTIME)
public #interface TrialMethod {
String name();
}
I learned that you can access the junit method through the junit class. Then getting the annotation value is trivial.
private void setTrialMethodByAnnotation() {
Class<?> clazz = this.getClass();
Class<TrialMethod> trialMethod = TrialMethod.class;
Method method = null;
try {
method = clazz.getMethod(this.getName(),null);
} catch (SecurityException e) {
logger.error(e.getMessage());
} catch (NoSuchMethodException e) {
logger.error(e.getMessage());
}
if(method.isAnnotationPresent(trialMethod)){
trialMethodModel.setName(method.getAnnotation(trialMethod).name());
...
}
}

Categories