我知道如果我需要模拟静态方法,这表明我的设计存在一些问题,但在我的情况下,这似乎不是设计问题。
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方法因其静态方法而不可见。
答案 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();
}
}