Reputation: 1304
I have a class called Price with constructor, which I am dynamically loading via reflection:
public Price(Context context, String pair) {
this.context = context;
this.value1 = pair.substring(0, 3);
this.value2 = pair.substring(3, 6);
this.dps = context.getService().getm1(value1, value2).getm2();
}
However I want to mock the Context object
and I want
context.getService().getm1(value1, value2).getm2()
to return 5.
Here is what I have tried
//mocking the Context class
Class<?> contextClass = urlClassLoader.loadClass("com.algo.Context");
constructor =contextClass.getConstructor();
Object context = Mockito.mock(contextClass);
//trying to instantiate the Price class
Class<?> priceClass = urlClassLoader.loadClass("com.algo.Price");
constructor = priceClass.getConstructor(contextClass,String.class);
Mockito.when(context.getService().getm1(value1, value2).getm2().thenReturn(5));
Object price = constructor.newInstance(context,"PRICES");
However I have a red line under
context.getService()
The error says
The method getService() is undefined for the type Object
How can I get around this, my end goal is to create the Price object with the variable
dps
being an int 5, that is why I want to mock the Context object.
Upvotes: 0
Views: 625
Reputation: 44995
For me the only way is to implement your whole test using reflection which is really laborious especially in your case as you will need to do the same thing for each method call as you cannot mock directly context.getService().getm1(value1, value2).getm2()
.
Assuming that I have a class Context
as below
public class Context {
public int getm1(String value1, String value2) {
return -1;
}
}
A normal test case would be:
@Test
public void normal() throws Exception {
Context context = Mockito.mock(Context.class);
Mockito.when(context.getm1(Mockito.anyString(), Mockito.anyString())).thenReturn(5);
Assert.assertEquals(5, context.getm1("foo", "bar"));
}
The same test using reflection would be:
@Test
public void reflection() throws Exception {
... // Here I get the classloader
// Get the class by reflection
Class<?> contextClass = urlClassLoader.loadClass("com.algo.Context");
// Mock the class
Object context = Mockito.mock(contextClass);
// Get the method by reflection
Method method = contextClass.getMethod("getm1", String.class, String.class);
// Invoke the method with Mockito.anyString() as parameter
// to get the corresponding methodCall object
Object methodCall = method.invoke(context, Mockito.anyString(), Mockito.anyString());
// Mock the method call to get what we expect
Mockito.when(methodCall).thenReturn(5);
// Test the method with some random values by reflection
Assert.assertEquals(5, method.invoke(context, "foo", "bar"));
}
Upvotes: 1
Reputation: 911
Cannot really understand this issue. If you are working with an unknown type it cannot be typed as Context within the construtor.
But independently, an approach would be to create interfaces representing the expected structure of context and then mock the interfaces to return the value. It is not necessary to really load the dynamic class within the test if it is mocked either way.
Upvotes: 0