Mockito/Powermock class 构造通用 class 扩展
Mockito/Powermock class construction for generic class extension
不确定我的问题措辞是否正确,但我正在尝试模拟 class 的构造,该 class 作为泛型传递到我要测试的对象中。下面是我正在测试的对象中发生的事情的示例:
MyClass(boolean historic, Class<? extends Learner> learner) {
this.learner = learner.newInstance();
this.historic = historic;
}
Learner 是我要模拟的,它是我构建的各种学习者 classes 的界面。我不想在这里测试他们的逻辑,这就是为什么我想嘲笑他们并控制他们 return。我正在尝试使用以下设置(静态学习器 class 没有构造函数参数):
@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();
}
问题是 Powermock 无法构造学习者,因为它说找不到构造函数。这是有道理的,因为 Learner class 只是一个接口。那么当 StaticLearner 只是从 Learner 继承的泛型时,我该如何模拟传入和构造的 StaticLearner?
这是我收到的错误:
org.powermock.reflect.exceptions.ConstructorNotFoundException:
No constructor found in class 'com.myco.processing.learners.Learner' with parameter types: [ <none> ].
将 PowerMockito.whenNew(Learner.class)
替换为 PowerMockito.whenNew(StaticLearner.class)
。例如,
@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
在使用 new
关键字时有效,例如 new StaticLearner()
。如果您使用 StaticLearner.class.newInstance()
.
它将不起作用
如果要模拟MyClass
,将Learner
对象的创建委托给新工厂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() {
...
}
}
现在模拟工厂 class 到 return 模拟 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();
}
}
显然对 learner.newInstance()
的调用没有参数。
即使有 id,它们也会作为参数传递给构造函数。
那么为什么不直接将 learner.newInstance()
的 结果 作为参数传递给这个构造函数呢?然后你可以传入一个 "regular" 模拟,你就不需要 PowerMock.
不确定我的问题措辞是否正确,但我正在尝试模拟 class 的构造,该 class 作为泛型传递到我要测试的对象中。下面是我正在测试的对象中发生的事情的示例:
MyClass(boolean historic, Class<? extends Learner> learner) {
this.learner = learner.newInstance();
this.historic = historic;
}
Learner 是我要模拟的,它是我构建的各种学习者 classes 的界面。我不想在这里测试他们的逻辑,这就是为什么我想嘲笑他们并控制他们 return。我正在尝试使用以下设置(静态学习器 class 没有构造函数参数):
@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();
}
问题是 Powermock 无法构造学习者,因为它说找不到构造函数。这是有道理的,因为 Learner class 只是一个接口。那么当 StaticLearner 只是从 Learner 继承的泛型时,我该如何模拟传入和构造的 StaticLearner?
这是我收到的错误:
org.powermock.reflect.exceptions.ConstructorNotFoundException:
No constructor found in class 'com.myco.processing.learners.Learner' with parameter types: [ <none> ].
将 PowerMockito.whenNew(Learner.class)
替换为 PowerMockito.whenNew(StaticLearner.class)
。例如,
@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
在使用 new
关键字时有效,例如 new StaticLearner()
。如果您使用 StaticLearner.class.newInstance()
.
如果要模拟
MyClass
,将Learner
对象的创建委托给新工厂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() { ... } }
现在模拟工厂 class 到 return 模拟
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(); } }
显然对 learner.newInstance()
的调用没有参数。
即使有 id,它们也会作为参数传递给构造函数。
那么为什么不直接将 learner.newInstance()
的 结果 作为参数传递给这个构造函数呢?然后你可以传入一个 "regular" 模拟,你就不需要 PowerMock.