简体   繁体   English

用于通用类扩展的Mockito / Powermock类构造

[英]Mockito/Powermock class construction for generic class extension

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. 问题是Powermock无法构造学习器,因为它说找不到构造函数。 That makes sense since the Learner class is just an interface. 这是有道理的,因为Learner类只是一个接口。 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) . PowerMockito.whenNew(Learner.class)替换为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();
    }

Update 更新资料

PowerMockito.whenNew works when new keyword is used, eg, new StaticLearner() . 当使用new关键字(例如new StaticLearner()时, PowerMockito.whenNew起作用。 It will not work if you use StaticLearner.class.newInstance() . 如果使用StaticLearner.class.newInstance() ,它将不起作用。

  • If you want to mock MyClass , delegate the creation of Learner object to a new factory class, LearnerFactory . 如果要模拟MyClass ,则将Learner对象的创建委托给新的工厂类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 . 现在模拟工厂类以返回模拟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(); } } 

Obvously the call to learner.newInstance() has no parameters. 显然,对learninger.newInstance learner.newInstance()的调用没有参数。 Even if id had they would be passed in as parameters to the constructor too. 即使id有,它们也将作为参数传递给构造函数。

So why don't you simply pass in the result of learner.newInstance() as parameter to this constructor? 那么,为什么不简单地将learner.newInstance()结果作为参数传递给此构造函数呢? Then you could pass in a "regular" mock and you would not need PowerMock . 然后,您可以传递“常规”模拟,并且不需要 PowerMock

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM