我知道如果我需要模拟静态方法,这表明我的设计存在一些问题,但就我而言,这似乎不是设计问题。
BundleContext bundleContext = FrameworkUtil.getBundle(ConfigService.class).getBundleContext();
在这里,FrameworkUtil 是一个存在于 api jar 中的类。在代码中使用它不能成为设计问题。
我的问题是在运行这条线时
FrameworkUtil.getBundle(ConfigService.class);
返回空 所以我的问题,有什么方法可以在运行时替换该空我正在使用 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
的字段及其资源库。 将此行添加到每个此类的构造符中
utilWrapper = new UtilWrapper();
并将每个对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());
}
}
单位:火直接调用静态方法,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();
}
}