-3

I wanted to write test for my changes, but got problem - changes were made inside static metod. The code looks like this

class GlobalData {
static boolean doSomething(...){...}
static xxx A() {...}
static yyy B() {...}
static void C() {
xxx a = A();
yyy b = B();

if (doSomething(a, b))
{
   a.xyz(b,42);
   ... my coode i want to test....
}
}

What I want is to mock methods A and B and doSomething and all these static methods that are used in method C, but I can't find any way to do that at the moment. Do you now any?

maxpovver
  • 1,580
  • 14
  • 25

3 Answers3

3

Consider using powerMock. It has an extension over Mockito called 'powerMockito'. It gives you capability to mock static methods also. https://github.com/jayway/powermock/wiki/MockitoUsage

Dhaval
  • 1,046
  • 6
  • 10
0

Since you can't override static methods, no, you cannot mock them in Mockito.

Andy Turner
  • 137,514
  • 11
  • 162
  • 243
  • Not with mockito alone, but with Powermockito you can: http://www.codeproject.com/Articles/806508/Using-PowerMockito-to-Mock-Final-and-Static-Method – Zoltán Aug 11 '15 at 15:53
  • The OP didn't ask about Powermockito. So... I stand by my answer. – Andy Turner Aug 11 '15 at 15:54
  • You can use PowerMockito. – Jose Martinez Aug 11 '15 at 15:58
  • that is true, however, apart from answering questions precisely, the purpose of this site is also to try to be helpful. If I knew you knew about Powermockito, I'd even find your answer a bit rude. If you didn't want to mention Powermockito because you think requiring Powermockito implies bad design (which I often agree with), than you should state that too. – Zoltán Aug 11 '15 at 20:15
0

You should/could use the Singleton pattern.

Basically all the static methods call an internal private object that do the actual logic (called the instance).

If you do this, you can provide a protected static method setInstance. During your test, you create a mocked instance and set it to the static class.

This is doable, but it's not the most elegant solution, but static calls are not that elegant in the first place. I'm answering as there was no possible way to refactor out the entire codebase (like using Dependency Injection for example)

For example:

class GlobalData {
    //private object that does all the actual logic
    private static GlobalData instance = new GlobalData();

    //constructor is private so no one can call it
    private GlobalData() {

    }

    //delegate the static call to the internal instance
    static boolean doSomething(...){ return instance._doSomething(); }

    //use underscore to keep similar name but avoid ambiguous call
    private boolean _doSomething(...){ ... }

    //same here
    static xxx A() { return instance._A(); }
    private xxx _A() {...}

    //this is not public, so must be called from the same package
    //since the constructor is private, no one will be able to create a GlobalData
    //except for mockito
    static void setInstance(GlobalData instance) {
        GlobalData.instance = instance;
    }
}

And then in your test (which should be in the same package):

GlobalData instanceMocked = mock(GlobalData.class);
//we mock the methods with underscore, as they are the instance methods, and
//not the class methods
when(instanceMocked._A()).thenReturn(whatever);
when(instanceMocked._doSomething()).thenReturn(whatever);
GlobalData.setInstance(instanceMocked);

This requires only a minor refactor in the class you are looking at, without touching the rest of the project, while achieving what you want.

Fermin Silva
  • 3,331
  • 2
  • 17
  • 21
  • I have used this approach in the past and it does work. There are issues with it, but it lead to easier unit-testing then the static methods approach. – Jose Martinez Aug 11 '15 at 16:10
  • Exactly. Don't abuse this nor consider it an excellent practice – Fermin Silva Aug 11 '15 at 16:12
  • Another point for this approach. While you can use PowerMockito to mock static methods, if messed up our JaCoCo reports. The byte-code manipulation that PowerMockito does, broke JaCoCo's byte-code manipulation. I'm sure the same may be true for any other code-coverage tool. – Jose Martinez Aug 11 '15 at 16:16
  • The probem is that when you are working on real job there is always lots of legacy that you'd better not touch. This is why I can't use singleton – maxpovver Aug 11 '15 at 17:09