java - 模拟构造函数,该构造函数在 java 中使用 Powermockito 提供基类引用

标签 java unit-testing mockito powermockito

这是场景,我的类 MyClass 的方法之一中有类似的内容

public class MyClass{

    public Object build(Map map) {

        BaseClass cls;     

        if(SomeconditionTrue) {

         cls = new ChildClass1(new ABC());

        } else {

        cls = new ChildClass2(new ABC());

       }

       cls.callMethod();

    }

}

对于上述场景,我正在使用 PowerMockito 编写一个测试用例,我想模拟这个方法调用,cls.callMethod()。当我尝试模拟时,它调用失败的实际方法 callMethod() 。有人可以帮我模拟该方法调用吗?尝试使用 PowerMockito PowerMockito.stub 和其他一些选项使用几个场景,但它总是调用实际方法。之所以要mock这个方法,是因为它的逻辑不同,调用的API也不同,方法比较复杂,所以需要mock这个方法。

最佳答案

您可以使用 Powermock 来解决此问题,但这不一定是此类问题的“最佳”答案。

本质上,您在代码中调用 new 的事实让您感到悲伤 - 您因此创建了难以测试的代码。你可能会看这些videos理解我在说什么。

长话短说:您可以重新编写代码,而不是求助于 Powermock 锤子;使用依赖注入(inject)。因此,被测试的类可以使用一些工厂对象来提供它所需的对象,而不是自己创建这些对象。然后您可以使用任何“普通”模拟框架(例如 EasyMock 或 Mockito)来创建该工厂的模拟版本。

编辑:我认为您可能使整个问题过于复杂化。您看,有一个基类或两个子类并不重要。事实是:对于每种测试方法,您应该准确了解将采用哪条路径。您要么想要创建一个child1,或者一个child。因此,我为您创建了一个简化的解决方案:

package ghostcat.test;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

class Abc {}

abstract class Base {
  void callMethod() {
    System.out.println("Base::callMethod");
  }
}

class ChildClass1 extends Base {
  ChildClass1(Abc abc) {}
}

class MyClass {
  public Object build() {
    System.out.println("build1");
    Base cls = new ChildClass1(new Abc());
    System.out.println("build2");
    cls.callMethod();
    System.out.println("build3");
    return null;
  } 
}

@RunWith(PowerMockRunner.class)
@PrepareForTest(MyClass.class)
public class MockNewTest {
  @Test
  public void test() throws Exception {
    ChildClass1 mock = Mockito.mock(ChildClass1.class);
PowerMockito.whenNew(ChildClass1.class).withArguments(Mockito.any(Abc.class)).thenReturn(mock);
    new MyClass().build();
}

}

打印:

build1
build2
build3

所以你可以看到 - 基类中没有任何内容被调用;只是因为该子对象被“完全”模拟。

重点是:您的测试中的代码只需要一个某种类型的对象;并且您事先知道那是 child1 还是 child2。因此,您只需为该类创建一个模拟;并使用 PowerMockito 返回您刚刚创建的模拟。

郑重声明:我玩过一段时间的 spy ;但他们在这里没有帮助;而且它们也不是必需的!

关于java - 模拟构造函数,该构造函数在 java 中使用 Powermockito 提供基类引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41169684/

相关文章:

java - 覆盖 Photoview 的单击

java - 是否有 API/代码可以从 kibana 视觉效果、仪表板、图表中获取 id 列表?

java - TestNG @Dataprovider

unit-testing - 如何使用 jUnit 正确编写 groovy 单元测试?

java - 为什么 Mockito 不会抛出异常?

java - Switch 语句和字符串到字节

java - 在 Eclipse 中找不到文件

java - 在两个项目之间共享 Android 测试

mockito - 使用 Mockito 和 InjectMocks 时未执行 Kotlin 惰性 block

android - 测试rxjava回调函数