当前位置: 首页 > 知识库问答 >
问题:

用Mockito截取真实的非静态方法调用

舒枫涟
2023-03-14

使用mockitopowermockito,是否有任何方法可以拦截对对象的非静态方法的调用,或者至少是对单例对象的非静态方法的调用?

以下类提供了一个示例:

public class Singleton {

  private static Singleton INSTANCE = null;

  private Singleton(Object parameter) {}

  public static Singleton getInstance(Object parameter) {
    if (INSTANCE == null) {
      INSTANCE = new Singleton(parameter);
    }
    return INSTANCE;
  }

  public String process(String a, String b) {
    return (a + b);
  }

  // Other methods
}

public class Foreign {

  private Foreign() {}

  public static void main(String[] args) {
    System.out.println(Singleton.getInstance(new Object()).process("alpha", "beta"));
  }
}
Singleton.getInstance(new Object()).process("alpha", "beta");
public class SubSingleton extends Singleton {

  public SubSingleton(Object parameter) {
    super(parameter);
  }

  public String process(String a, String b) {
    if ("alpha".equals(a) && "beta".equals(b)) {
      return a + "-" + b;
    }
    return super.process(a + b);
  }
}
Object parameter = new Object();
PowerMockito.doReturn(new SubSingleton(parameter)).when(Singleton.class, "getInstance", parameter);

但是,上面的singleton类只提供了一个私有构造函数,因此不能对其进行扩展。使用PowerMockito.WhenNew()返回部分模拟(spy)也不会起作用,因为Singleton类不提供无参数构造函数。

想要的嘲弄能以其他任何方式实现吗?对于非单例类可以这样做吗?

共有1个答案

郭业
2023-03-14

首先,您可以将whenNew用于带有构造函数的对象,该构造函数带有一些参数:

@RunWith(PowerMockRunner.class)
@PrepareForTest(Singleton.class)
public class SingletonPrivateNewTest {

    @Mock
    Singleton singletonMock;

    @Before
    public void setUp() throws Exception {
        PowerMockito.whenNew(Singleton.class)
                .withAnyArguments()
                .thenReturn(singletonMock);
    }

    @Test
    public void testMockNew() throws Exception {
        Mockito.when(singletonMock.process(anyString(), anyString())).thenReturn("sasa");
        Foreign.main(new String[0]);
    }
}

其次,为什么不存根getInstance而不是new:

@RunWith(PowerMockRunner.class)
@PrepareForTest(Singleton.class)
public class SingletonPrivateNewTest {

    @Test
    public void testMockNew() {
        PowerMockito.mockStatic(Singleton.class);
        Singleton singletonMock = Mockito.mock(Singleton.class);
        PowerMockito.when(Singleton.getInstance(any())).thenReturn(singletonMock);
        Mockito.when(singletonMock.process(anyString(), anyString())).thenReturn("sasa");
        Foreign.main(new String[0]);
    }
}

再次,要截取的过程方法:

    null
@RunWith(PowerMockRunner.class)
@PrepareForTest(Singleton.class)
public class SingletonPrivateNewTest {

    @Test
    public void testMockNew() {
        var singletonReal = Singleton.getInstance(new Object());
        var singletonMock = Mockito.mock(Singleton.class);
        PowerMockito.mockStatic(Singleton.class);
        PowerMockito.when(Singleton.getInstance(any())).thenReturn(singletonMock);
        Mockito.when(singletonMock.process(anyString(), anyString())).thenAnswer((args) -> {
            String a = args.getArgument(0);
            String b = args.getArgument(1);
            if ("alpha".equals(a) && "beta".equals(b)) {
                return "sasa";
            } else {
                return singletonReal.process(a, b);
            }
        });
        Foreign.main(new String[0]);
    }
}

最后,使用间谍而不是模仿者

@RunWith(PowerMockRunner.class)
@PrepareForTest(Singleton.class)
public class SingletonPrivateNewTest {

    @Test
    public void testMockNew() {
        var singletonReal = Singleton.getInstance(new Object());
        var singletonMock = Mockito.spy(singletonReal);
        PowerMockito.mockStatic(Singleton.class);
        PowerMockito.when(Singleton.getInstance(any())).thenReturn(singletonMock);
        Mockito.when(singletonMock.process("alpha", "beta")).thenReturn("sasa");
        // NOTE: real method is called for other args
        Foreign.main(new String[0]);
    }
}

 类似资料:
  • 我最近对 PHP 5.4 进行了更新,但收到有关静态和非静态代码的错误。 这是错误: 这是第371行: 我希望有人能帮忙。

  • 实际的方法是在第3行被调用()。我已经添加了和注释。 为什么调用实际方法?我也尝试了PowerMockito.do返回,但是得到了同样的问题。

  • 问题内容: 尝试在静态类中调用非静态方法时遇到错误。 无法从类型播放中静态引用非静态方法methodName() 我不能使该方法静态,因为这也给我一个错误。 此静态方法无法从xInterface隐藏实例方法 有什么办法可以在另一个静态方法中轮回调用非静态方法?(这两种方法位于单独的包和单独的类中)。 问题答案: 从静态方法中调用非静态方法的唯一方法是使类的实例包含非静态方法。根据定义,非静态方法是

  • 问题内容: 我正在尝试使用此功能,但正在收到消息。 我可以简单地使其静态化,从而解决了我的问题,但是如果不走那条路线怎么办。我想保持方法非静态。 以下是一些代码,可让您了解发生了什么: 问题答案: 创建您的课程的实例 这是一个实例方法,它需要一个实例来访问它。请阅读有关类和对象的官方教程。

  • 我正在使用存储库模式并尝试建立模型之间的关系。当我尝试运行存储()方法(在控制器中),该方法试图使用用户()方法(与方模型建立关系)时,我收到以下错误消息: 非静态方法不应该静态调用::user(),假设$this来自不兼容的上下文 我不明白为什么在尝试运行user()relationship方法时会出现此错误,但所有其他方法(包括$this- 以下是相关代码:

  • 问题内容: Java-8允许在接口内部定义静态方法,但仅通过接口名称限制其调用: 9.4:接口可以声明静态方法,这些方法在不引用特定对象的情况下被调用。 例如: 导致错误: 在JLS中,这种禁令经常有一种解释。在这种情况下,我没有发现任何详细信息。因此,我正在寻找对此规则的全面或权威的解释:为什么禁止通过特定的对象引用调用静态方法?它有什么坏处? 问题答案: 相当强烈的共识是,有关类的静态方法也不