Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PowerMock, mockito, verify static method

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!

like image 281
Kevin Avatar asked Mar 12 '11 21:03

Kevin


People also ask

How do you verify a static method is called in Mockito?

To define mock behavior and to verify static method invocations, use the MockedStatic reference returned from the Mockito. mockStatic() method. It is necessary to call ScopedMock. close() method to release the static mock once it has been used and is no longer needed.

What does PowerMock verify do?

The main aim of PowerMock is to extend the existing APIs with some methods and annotations to provide extra features that make unit testing quite easy. The PowerMock framework provides a class called PowerMockito used to create mock objects and initiates verification and expectation.

Is PowerMock compatible with Mockito?

PowerMock uses internal Mockito API, but at least it possible to use both mocking framework together.


2 Answers

I don't know as of which version, but PowerMockito.verifyStatic(VerificationMode) is deprecated. Just wanted to point that out to anyone else finding this years after the last post.

like image 106
vnavs Avatar answered Oct 25 '22 08:10

vnavs


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.

like image 36
Jianyu Avatar answered Oct 25 '22 09:10

Jianyu