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.