我已经用我的代码做了一个小例子来说明问题
public class SiteTranslator {
Integer id;
//Other fields
}
public class SiteUtil {
private static SiteTranslator siteTranslator = getSiteTranslator();
private static SiteTranslator getSiteTranslator()
{
SiteTranslator siteTranslator;
//Logic involving network call
return siteTranslator;
}
private static String getEnvironment()
{
String env = "";
//Logic
return env;
}
public static int getParent(int siteId)
{
int parentId = 0;
//Logic using siteTranslator from getSiteTranslator()
return parentId;
}
}
public class SiteUtilTest {
@Test
public void test1()
{
try
{
PowerMockito.suppress(SiteUtil.class.getMethod("getSiteTranslator"));
BDDMockito.given(SiteUtil.getParent(1)).willReturn(6);
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
我们从getSiteTranslator()方法获得的SiteTranslator对象由我的公共函数getParent()使用。由于getSiteTranslator()需要网络调用,因此需要对其进行抑制。但是我收到以下错误
java.lang.NoSuchMethodException: SiteUtil.getSiteTranslator()
我认为问题是因为我正在尝试模拟私有静态函数。但是我无法将其改为公开。有没有办法在当前状态下模拟代码。
答案 0 :(得分:2)
事实上,您不需要Powermockito来实现您的需求。
目前,您认为需要Powermockito来抑制私有静态方法,但这绝对不是可行的方法。
相反,您应该重构代码以便更容易测试:
static
限定符在这样的重构之后,你最终会得到类似的东西(不需要嘲笑!):
public class SiteUtil {
private SiteTranslator siteTranslator;
public SiteUtil(SiteTranslator siteTranslator) {
this.siteTranslator = siteTranslator;
}
public int getParent(int siteId) {
int parentId = 0;
// Logic using siteTranslator
return parentId;
}
...
}
现在你可以这样测试:
public class SiteUtilSpec {
private final SiteTranslator defaultTranslator = new DummySiteTranslator();
@Test
public void itShouldReturnTheSixthSiteWhenWeProvideTheFirstParent() {
SiteUtil site = new SiteUtil(defaultTranslator);
int parentId = site.getParent(1);
assertEquals(6, parentId);
}
}
DummySiteTranslator
是一个假对象(也许它嵌入了一堆对测试有用的硬编码翻译)但重点是该对象永远不会进行任何网络调用!使其安全,快速(非常适合测试)。
答案 1 :(得分:1)
“Spotted”的答案已经指出了它,因为核心问题是:你为绝对没有原因创建了难以测试的代码。
使用此类内部静态调用只会使您的程序难以测试;并且惊喜:它还使得难以来维护,增强和重用。您需要转向Powermock的事实通常只是表明您的生产代码错误。现在,您可以选择使用PowerMock“修复”该问题;或者通过更改生产代码来真正解决问题 - 以示例代码的方式解决问题是不好的做法!
所以,这里的另一个真正的教训是:你想花一些时间来学习如何编写没有这些问题的代码;例如,通过观看那些videos。