Java 模拟某个jar中存在的静态方法的替代方法

Java 模拟某个jar中存在的静态方法的替代方法,java,junit,mockito,powermock,Java,Junit,Mockito,Powermock,我知道,如果我需要模拟一个静态方法,这表明我的设计有一些问题,但在我的情况下,这似乎不是一个设计问题 BundleContext bundleContext = FrameworkUtil.getBundle(ConfigService.class).getBundleContext(); 这里FrameworkUtil是api jar中的一个类。在代码中使用它不是设计问题 BundleContext bundleContext = FrameworkUtil.getBundle(Config

我知道,如果我需要模拟一个静态方法,这表明我的设计有一些问题,但在我的情况下,这似乎不是一个设计问题

BundleContext bundleContext = FrameworkUtil.getBundle(ConfigService.class).getBundleContext();
这里FrameworkUtil是api jar中的一个类。在代码中使用它不是设计问题

BundleContext bundleContext = FrameworkUtil.getBundle(ConfigService.class).getBundleContext();
我的问题是在运行这条线路时

FrameworkUtil.getBundle(ConfigService.class); 
返回null,那么我的问题是,有什么方法可以在运行时替换null 我正在使用Mockito framewrok,我的项目不允许我使用powermock

如果我使用

doReturn(bundle).when(FrameworkUtil.class)

这样,getBundle方法就不可见了,因为它是一个静态方法。

您是正确的,这不是您的设计问题。但是,如果没有PowerMock,您的选择会变得有点模糊

我建议为FrameworkUtil类创建一个非静态包装器,您可以将其注入和模拟

更新:(大卫·华莱士)

因此,您向应用程序添加了一个新类,如下所示

public class UtilWrapper {
    public Bundle getBundle(Class<?> theClass) {
        return FrameworkUtil.getBundle(theClass);
    }
}
并将对
FrameworkUtil.getBundle
的每个调用替换为
utilWrapper.getBundle

现在在您的测试中,您制作了一个模拟的
UtilWrapper
,并将其存根,以返回您喜欢的
Bundle

when(mockUtilWrapper.getBundle(ConfigService.class)).thenReturn(someBundleYouMade);
对于您正在测试的类,可以调用
setUtilWrapper(mockUtilWrapper)
或其他任何东西。如果使用的是
@InjectMocks
,则不需要执行最后一步

现在,您的测试应该结合在一起,但是使用模拟的
UtilWrapper
,而不是依赖于
FrameworkUtil

单元测试的测试

package x;

import static org.junit.Assert.*;

import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;

public class GunTest {

  @Before
  public void setUp() throws Exception {
  }

  @Test
  public void testFireTrue() {
    final Gun unit = Mockito.spy(new Gun());
    Mockito.doReturn(5).when(unit).getCount();
    assertTrue(unit.fire2());
  }

  @Test
  public void testFireFalse() {
    final Gun unit = Mockito.spy(new Gun());
    Mockito.doReturn(15).when(unit).getCount();
    assertFalse(unit.fire2());
  }

}
该股: fire直接调用静态方法, fire2排除对受保护方法的静态调用:

package x;

public class Gun {

  public boolean fire() {
    if (StaticClass.getCount() > 10) {
      return false;
    }
    else {
      return true;
    }
  }

  public boolean fire2() {
    if (getCount() > 10) {
      return false;
    }
    else {
      return true;
    }
  }

  protected int getCount() {
    return StaticClass.getCount();
  }
}

这是正确的做法+1.ankit,如果你需要更多的帮助来了解如何做到这一点,请在这里发表评论,我将编辑@Dave的答案以包含一些实际的代码。我使用powermock通过间谍来处理这个问题,并重构我的代码。例如:而不是:int count=StaticClass.getCount();I-do:int-count=getCount();在“getCount”方法中,有一行调用“StaticClass.getCount()”。使用“间谍”时,非静态的“getCount”永远不会被调用,“StaticClass.getCount();”行永远不会被执行。那么也许你应该发布一个单独的答案,详细说明你的操作方法。@DavidWallace如果我为该类创建一个包装器,那么我也需要调用该静态方法,并最终得到相同的问题。如果你能给我一些工作代码,那就太好了。或者只是一点点that@ankit,但下一个发现堆栈溢出问题的人可能被允许使用PowerMock。因此,我认为TitiWangsaBinDamhore发布一个答案是有价值的,即使它对您没有帮助。纯Mockito没有Powermock处理静态方法调用。看来您接近答案了,您可以根据我的情况更改此代码吗如果OP在这个特定类中只使用一个静态方法,您的解决方案是优雅的(+1)。如果在其他地方使用相同的方法或来自相同类的其他静态方法,则需要重复该模式,这通常意味着设计不好。我同意Dave的观点。我们最终会得到多个具有相同方法名称和相同方法体的类。Sonarqube会抱怨。DRY。您没有显示调用任何静态方法的代码d该点在TitiWangsaBinDamhore保持不变