抛出异常,每当使用PowerMock(EasyMock)调用包保护的静态方法时。

huangapple go评论72阅读模式
英文:

Throw Exception Whenever Package Protected Static Method Is Called Using PowerMock (EasyMock)

问题

I'm trying to throw an assertion exception whenever the TimeZone.getDefaultRef() method is called, to basically show that this method is never called during the test. The problem is that it's package protected and static, so I think I'm forced to use PowerMock. Here's my attempt:

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

I'm getting the error java.lang.IllegalStateException: no last call on a mock available, which I've definitely seen before but am not sure how to fix in this context. I'm also open to any other more elegant way to accomplish this. To sum up:

  1. Test should fail if Timezone.getDefaultRef() is ever called
  2. Test shouldn't fail just because the method is never called (EasyMock is expecting the method but it never comes)
  3. One test failing shouldn't affect the other tests
  4. Everything else about the TimeZone class should operate normally
英文:

I'm trying to throw an assertion exception whenever the TimeZone.getDefaultRef() method is called, to basically show that this method is never called during the test. The problem is that it's package protected and static, so I think I'm forced to use PowerMock. Here's my attempt:

@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);
    {

I'm getting the error java.lang.IllegalStateException: no last call on a mock available, which I've definitely seen before but am not sure how to fix in this context. I'm also open to any other more elegant way to accomplish this. To sum up:

  1. Test should fail if Timezone.getDefaultRef() is ever called
  2. Test shouldn't fail just because the method is never called (EasyMock is expecting the method but it never comes)
  3. One test failing shouldn't affect the other tests
  4. Everything else about the TimeZone class should operate normally

答案1

得分: 1

我正在尝试找到一种解决方法,但快速答案是该方法未被模拟。在期望过程中实际调用了真实方法。

PowerMock 无法模拟由引导类加载器加载的类。TimeZone 就是其中之一。

解决方法是模拟调用它的类。这在这里有解释。它说你需要准备调用系统类的类,而不是系统类本身。

但在你的情况下,我不确定是否可以这样做。因为你想知道是否有地方在调用你的类。所以,如果你要查找的是调用 TimeZone 的东西,那么你不能准备任何使用 TimeZone 的东西。除非你有可能调用者的有限范围。

英文:

I am trying to find a workaround but the quick answer is that the method is not mocked. The real method is called instead during the expectation.

PowerMock can't mock classes loaded by the bootstrap class loader. TimeZone is one of those.

The solution is to mock with is calling it. It's explained here. It says you need to prepare the class calling the system class instead of the system class.

But in your case, I'm not sure you can. Because you want to know if something somewhere is calling your class. So you can't prepare whatever is using TimeZone if that is was you are looking for. Unless you have a limited scope of possible callers.

huangapple
  • 本文由 发表于 2020年8月7日 23:29:10
  • 转载请务必保留本文链接:https://go.coder-hub.com/63304840.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定