PowerMock, mockito, verify static method

2019-04-20 09:20发布

问题:

I'm trying to get PowerMock to work with mockito, and I'm following the documentation here: http://code.google.com/p/powermock/wiki/MockitoUsage13.

To simplify a bit, lets say that I have a static method:

StaticObj.put(String key, String val) { ... }

And the class to be tested does something like this:

public class ClassToTest {
    public void doSomething(Params p) {
        if (StringUtils.isNotBlank(p.getK()) StaticObj.put("k1", p.getK());
        if (StringUtils.isNotBlank(p.getX()) StaticObj.put("x1", p.getX());
    }
}

In my unit test I'd like to verify that StaticObj.put is called for K and X when they are not blank or null, so I do something like this:

public void testNormalCase() {
    // assume that mocking setup for statics already happened in some @Before function..
    Params params = new Params("k", "x");
    ClassToTest classToTest = new ClassToTest();
    classToTest.doSomething(params);

    // now I want to verify:
    PowerMockito.verifyStatic(times(1));
    StaticObj.put("k1", "k1");

    PowerMockito.verifyStatic(times(1));
    StaticObj.put("x1", "x");
}

This works, and it's what I'd expect. What doesn't work, is if I comment out the verification for K, then the verification for X fails! The error message indicates that ("x1", "x") is expected but got ("k1", "k"). Why is this? Am I not coding this correctly?

Also it leads me to believe that the following type of test, which passes, might pass for the wrong reason entirely:

public void testOtherCase() {
    // assume that mocking setup for statics already happened in some @Before function..
    Params params = new Params("k", null);
    ClassToTest classToTest = new ClassToTest();
    classToTest.doSomething();

    // now I want to verify:

    PowerMockito.verifyStatic(never());
    StaticObj.put(eq("x1"), anyString());
}

E.g. I wonder if powermock sees "k1", decides that "x1" was never called, and passes. (?)

To state it generally, I have a static method that is called N times (where N changes depending on the input params). And I want to verify that it was called in the correct cases (which can be determined by input params). It seems like powermock doesn't handle this well, unless I misunderstand.

Thanks for any ideas!

回答1:

I read this question and the issue carefully but not sure if I understood them clearly - From my understanding, it's correct that powermock raise the exception when you pass k and x but only verify k.

Because you are mocking the static method StaticObj.put, when you pass parameter k and x and verify it with

PowerMockito.verifyStatic(times(1));
StaticObj.put("k1", "k1");

PowerMockito.verifyStatic(times(1));
StaticObj.put("x1", "x"); 

This should work. And when you verify parameter k and x with verification for k is commented out.

// PowerMockito.verifyStatic(times(1));
// StaticObj.put("k1", "k1");

PowerMockito.verifyStatic(times(1));
StaticObj.put("x1", "x");

Powermock will get the invocation with put("k1"...) first apparently, so the verification of x will raise an error. Your verification process is sequenced.