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

时间:2013-11-13 05:39:52

标签: java junit mockito powermock

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

BundleContext bundleContext = FrameworkUtil.getBundle(ConfigService.class).getBundleContext();

这里的FrameworkUtil是api jar中的一个类。在代码中使用它不能成为一个设计问题。

我的问题在于运行此行

FrameworkUtil.getBundle(ConfigService.class); 

返回null所以我的问题是,有什么办法可以在运行时替换null 我正在使用Mockito framewrok,我的项目不允许我使用powermock。

如果我使用

doReturn(bundle).when(FrameworkUtil.class)

这样,getBundle方法因其静态方法而不可见。

2 个答案:

答案 0 :(得分:9)

你是对的,这不是你的设计问题。没有PowerMock,你的选择会变得有点模糊。

我建议为FrameworkUtil类创建一个非静态包装器,您可以注入并模拟它。

更新(David Wallace)

所以你在你的应用程序中添加一个新类,就像这样

public class UtilWrapper {
    public Bundle getBundle(Class<?> theClass) {
        return FrameworkUtil.getBundle(theClass);
    }
}

这个类很简单,你不需要对它进行单元测试。作为一般原则,您应该只为那些具有某种逻辑的方法编写单元测试 - 分支,循环或异常处理。单行不应进行单元测试。

现在,在您的应用程序代码中,为当前调用UtilWrapper的每个类添加一个类型为FrameworkUtil.getBundle的字段和一个setter。将此行添加到每个此类类的构造者

utilWrapper = new UtilWrapper();

并将FrameworkUtil.getBundle的所有来电替换为utilWrapper.getBundle

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

when(mockUtilWrapper.getBundle(ConfigService.class)).thenReturn(someBundleYouMade);

对于您正在测试的课程,请致电setUtilWrapper(mockUtilWrapper)或其他任何内容。如果您使用@InjectMocks,则不需要执行此最后一步。

现在,您的测试应该全部挂起,但使用您的模拟UtilWrapper而不是依赖FrameworkUtil的那个。

答案 1 :(得分:2)

单元测试

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();
  }
}