Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mock a static method multiple times using JMockit within a JUnit test

I have a class with static methods that I'm currently mocking with JMockit. Say it looks something like:

public class Foo {
    public static FooValue getValue(Object something) {
        ...
    }
    public static enum FooValue { X, Y, Z, ...; }
}

I have another class (let's call it MyClass) that calls Foo's static method; I'm trying to write test cases for this class. My JUnit test, using JMockit, looks something like this:

public class MyClassTest extends TestCase {
    @NonStrict private final Foo mock = null;

    @Test public void testMyClass() {
        new Expectations() {
            {
                Foo.getValue((Object) any); result = Foo.FooValue.X;
            }
        };
    }

    myClass.doSomething();
}

This works fine and dandy, and when the test is executed my instance of MyClass will correctly get the enum value of Foo.FooValue.X when it calls Foo.getValue().

Now, I'm trying to iterate over all the values in the enumeration, and repeatedly run the test. If I put the above test code in a for loop and try to set the result of the mocked static method to each enumeration value, that doesn't work. The mocked version of Foo.getValue() always returns Foo.FooValue.X, and never any of the other values as I iterate through the enumeration.

How do I go about mocking the static method multiple times within the single JUnit test? I want to do something like this (but obviously it doesn't work):

public class MyClassTest extends TestCase {
    @NonStrict private final Foo mock = null;

    @Test public void testMyClass() {

        for (final Foo.FooValue val : Foo.FooValue.values() {

            new Expectations() {
                {
                    // Here, I'm attempting to redefine the mocked method during each iteration
                    // of the loop. Apparently, that doesn't work.
                    Foo.getValue((Object) any); result = val;
                }
            };

            myClass.doSomething();
        }

    }
}

Any ideas?

like image 911
pmc255 Avatar asked Feb 04 '11 23:02

pmc255


People also ask

Can static methods be mocked using Mockito?

As previously mentioned, since Mockito 3.4. 0, we can use the Mockito. mockStatic(Class<T> classToMock) method to mock invocations to static method calls. This method returns a MockedStatic object for our type, which is a scoped mock object.

Why should we not mock static methods?

If you need to mock a static method, it is a strong indicator for a bad design. Usually, you mock the dependency of your class-under-test. If your class-under-test refers to a static method - like java.

Can you mock a static class MOQ?

You can use Moq to mock non-static methods but it cannot be used to mock static methods.


1 Answers

Instead of "mocking the method multiple times", you should record multiple consecutive return values in a single recording:

public class MyClassTest extends TestCase
{
    @Test
    public void testMyClass(@Mocked Foo anyFoo)
    {
        new Expectations() {{
            Foo.getValue(any);
            result = Foo.FooValue.values();
        }};

        for (Foo.FooValue val : Foo.FooValue.values() {
            myClass.doSomething();
        }
    }
}

It could also be done with a Delegate, if more flexibility was required.

like image 53
Rogério Avatar answered Sep 22 '22 16:09

Rogério