Java 使用PowerMock(EasyMock)调用包保护的静态方法时引发异常

Java 使用PowerMock(EasyMock)调用包保护的静态方法时引发异常,java,powermock,easymock,Java,Powermock,Easymock,无论何时调用TimeZone.getDefaultRef()方法,我都会尝试抛出一个断言异常,以表明在测试期间从未调用过该方法。问题是它是包保护的和静态的,所以我想我不得不使用PowerMock。以下是我的尝试: @RunWith(PowerMockRunner.class) @PrepareForTest(TimeZone.class) public class RandomTestingClass { @Before public void setup() {

无论何时调用TimeZone.getDefaultRef()方法,我都会尝试抛出一个断言异常,以表明在测试期间从未调用过该方法。问题是它是包保护的和静态的,所以我想我不得不使用PowerMock。以下是我的尝试:

@RunWith(PowerMockRunner.class)
@PrepareForTest(TimeZone.class)
public class RandomTestingClass {
    @Before
    public void setup() {
        PowerMock.mockStaticPartialNice(TimeZone.class, "getDefaultRef")
        PowerMock.expectPrivate(TimeZone.class, 
            TimeZone.class.getDeclaredMethod("getDefaultRef")).andStubThrow(new AssertionError());
        PowerMock.replay(TimeZone.class)
    }

    @Test
    public void randomTestThatShouldFailBecauseMethodCallsGetDefaultRefMethod() {
        Calendar.getInstance();
    }

    @Test
    public void randomTestThatShouldPassBecauseMethodDoesNotCallGetDefaultRefMethod() {
        Calendar.getInstance(TimeZone.getTimeZone("GMT"));
    }

    @After
    public void after() {
        PowerMock.verify(TimeZone.class);
    {

我得到了一个错误java.lang.IllegalStateException:没有最后一个mock调用可用,我以前肯定看到过,但不确定如何在这个上下文中修复。我也愿意接受任何其他更优雅的方式来实现这一点。总而言之:

  • 如果调用了
    Timezone.getDefaultRef()
    ,测试将失败
  • 测试不应该因为从未调用该方法而失败(EasyMock期待该方法,但它从未出现)
  • 一个测试失败不应影响其他测试
  • TimeZone类的所有其他内容都应该正常运行

  • 我试图找到一个解决办法,但快速的答案是,该方法没有被嘲笑。在期望过程中调用实方法

    PowerMock无法模拟引导类加载程序加载的类<代码>时区就是其中之一

    解决方案是使用调用它的对象进行模拟。已经解释过了。它说您需要准备调用系统类而不是系统类的类


    但对你来说,我不确定你能不能。因为你想知道是否有什么东西在召唤你的班级。因此,如果您正在寻找的是
    时区,那么您就无法准备任何东西。除非您的潜在客户有限。

    再次感谢您。我发现这个堆栈溢出的答案可能会提供一些线索。既然它被委托给sun.util类,那么在上使用Powermock是实现这一点的可行策略吗?好的。我找到了我要找的东西。所以我更新了我的答案。但我不认为你有一个简单的解决办法。除非你使用ByteBuddy或Byteman之类的东西。嗨,亨利,首先,再次感谢你真的超越了这一点。这就是我一直在寻找的答案(但不是希望的)。我正在研究AspectJ运行时编织注释,但我认为在这一点上,最好是手动遍历代码库并搜索所有有问题的方法,而不是尝试这种有点随意的自动化方法。再次感谢!不客气。我认为AspectJ也会有同样的问题。除非它现在可以使用Java代理。简单的替代方法是将断点放在您不希望的位置,如果您从未在断点处停止,那么就可以了。当然,这不是自动测试……啊,出于某种原因,我甚至没有考虑断点。不是完全自动化的,但在我完成一个类并修复所有内容之后,会进行一次良好的理智检查,以确保它不在那里。