Not sure I worded the question correctly but I'm trying to mock the construction of a class that is being passed as a generic into the object I want to test. Example below of what is taking place in the object I am testing:
MyClass(boolean historic, Class<? extends Learner> learner) {
this.learner = learner.newInstance();
this.historic = historic;
}
Learner is what I'm trying to mock and it is an interface for various learner classes I've built. I'm not trying to test their logic here which is why I want to mock them and control what they return. I'm trying to use the following setup (the static learner class has no constructor arguments):
@Test
@PrepareForTest({MyClass.class, Learner.class, StaticLearner.class})
public void test() {
Learner mockLearner = Mockito.mock(StaticLearner.class);
PowerMockito.whenNew(Learner.class)
.withNoArguments()
.thenReturn(mockLearner);
MyClass myClass = new MyClass(true, StaticLearner.class);
myClass.process();
}
Problem is Powermock is not able to construct the learner because it says no constructor can be found. That makes sense since the Learner class is just an interface. So how do I mock the StaticLearner being passed in and constructed when its simply a generic inheriting from Learner?
Here is the error I receive btw:
org.powermock.reflect.exceptions.ConstructorNotFoundException:
No constructor found in class 'com.myco.processing.learners.Learner' with parameter types: [ <none> ].
Replace PowerMockito.whenNew(Learner.class)
with PowerMockito.whenNew(StaticLearner.class)
. For example,
@Test
@PrepareForTest({MyClass.class})
public void test() throws Exception {
StaticLearner mockLearner = Mockito.mock(StaticLearner.class);
PowerMockito.whenNew(StaticLearner.class)
.withNoArguments()
.thenReturn(mockLearner);
MyClass myClass = new MyClass(true, StaticLearner.class);
myClass.process();
}
PowerMockito.whenNew
works when new
keyword is used, e.g, new StaticLearner()
. It will not work if you use StaticLearner.class.newInstance()
.
If you want to mock MyClass
, delegate the creation of Learner
object to a new factory class, LearnerFactory
.
public class LearnerFactory {
public static Learner getInstance(
Class<? extends Learner> learner) throws IllegalAccessException, InstantiationException {
return learner.newInstance();
}
}
public class MyClass {
private boolean historic;
private Learner learner;
public MyClass(boolean historic,
Class<? extends Learner> learner) throws IllegalAccessException, InstantiationException {
this.learner = LearnerFactory.getInstance(learner);
this.historic = historic;
}
public void process() {
...
}
}
Now mock the factory class to return the mock StaticLearner
.
@RunWith(PowerMockRunner.class)
@PrepareForTest({MyClass.class, LearnerFactory.class})
public class MyClassTest {
@Test
public void test2() throws Exception {
StaticLearner mockLearner =
PowerMockito.mock(StaticLearner.class);
//if needed
when(mockLearner.doSomething(anyString()))
.thenReturn("dummy");
PowerMockito.mockStatic(LearnerFactory.class);
when(LearnerFactory.getInstance(eq(StaticLearner.class)))
.thenReturn(mockLearner);
MyClass myClass = new MyClass(true, StaticLearner.class);
myClass.process();
}
}