开发者

Is this possible in Mockito: when(SomeClass.getIntance()).thenReturn(myMock)?

开发者 https://www.devze.com 2023-02-26 14:14 出处:网络
I\'m working with some legacy code, where I have to implement a new Handler. And in this handler, there\'s an object which is unfortunately initialized by the framework using some hard-coded property

I'm working with some legacy code, where I have to implement a new Handler. And in this handler, there's an object which is unfortunately initialized by the framework using some hard-coded property file, like this:

// new code
public class NewHandler extends RootHandler {
  Util util = Util.getInstance(); // !!!Problem: throws NPE in unit-testing env

  // defined in the legacy framework, can't change its signature
  @Override
  public void doSth() {

  }
}

// legacy code
public class Util {
    static public synchronized Util getInstance() { 
        if (_instance == null) {
            _instance = new Util();
        }
        return _instance;
    }

    private Util() {
    MyObj obj = LegacyCode.load("myConfig.cfg"); // !!!Problem: throws NPE in unit-testing env
    ...

}

}

Now the problem:

in Util(), it's always loading the config file from a fixed location, therefore it always throws NPE when I run my unit tests, since there's no "myConfig.cfg" on the unit-test classpath.

One workaround is to extract the business logic into a separate method, passing in an Util object, so that I can pass in mock objects during tests:

// new code
public class NewHandler extends RootHandler {
  Util util = null;

  // defined in the legacy framework, can't change its signature
  @Override
  public void handle() {
    Util util = util.getInstance();
    doHandle(util);
  }

  public void doHandle(Util util) {
    ...
  }
}

// legacy code
public class Util {
  ...
}

My question is:

is there any other way to workaround this problem, without adding the doHandle() method? I tried the following code using Mockito:

Util myUtil = mock(Util.class);
when(Util.getInstance()).thenReturn(myUtil);

but it didn't work, Util.getInstance() didn't get replaced with myUtil.

any thoughts?

UPDATE: Things are getting a little bit messy, as I found out that Util.getInstance() is called everywhere in the legacy code base. So even if I have a mocked Util in my new code (as was described by Stas below), things will still break whe开发者_如何学编程n Util.getInstance() is called elsewhere.

Obviously I couldn't add new Constructors to every single class in the legacy code that calls Util.getInstance().

This is the reason I'm asking "whether it's possible to have something in Mockito like when(Sth.getInstance()).thenReturn(myMock)"

if yes, the all the calls to Util.getInstance() can be mocked and won't cause problem anymore.

Hmm....Any idea?

***********************************************************************

SOLUTION: I think the solution in my case is PowerMock


You should try smt like

 public class NewHandler extends RootHandler {
     Util util;
     //Pass instance
     NewHandler(Util util) {this.util = util;}
 }

Than you will able to use it new NewHandler(Util.getInstance()) or new NewHandler(mock(Util.class)) in your tests.

PS for further info you can read about Service locator and DI

0

精彩评论

暂无评论...
验证码 换一张
取 消