新しいハンドラーを実装する必要があるレガシーコードを使用しています。そして、このハンドラーには、次のように、ハードコードされたプロパティ ファイルを使用してフレームワークによって残念ながら初期化されるオブジェクトがあります。
// 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
...
}
}
問題:
ではUtil()
、常に固定の場所から構成ファイルをロードしているため、単体テストのクラスパスに「myConfig.cfg」がないため、単体テストを実行すると常に NPE がスローされます。
1 つの回避策は、ビジネス ロジックを別のメソッドに抽出し、Util オブジェクトを渡して、テスト中にモック オブジェクトを渡すことができるようにすることです。
// 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 {
...
}
私の質問は:
doHandle() メソッドを追加せずに、この問題を回避する他の方法はありますか? Mockito を使用して次のコードを試しました。
Util myUtil = mock(Util.class);
when(Util.getInstance()).thenReturn(myUtil);
Util.getInstance() は myUtil に置き換えられませんでした。
何かご意見は?
更新: Util.getInstance() がレガシー コード ベースのあらゆる場所で呼び出されていることがわかったため、少し面倒です。そのため、新しいコードにモック化された Util がある場合でも (以下で Stas が説明したように)、別の場所で Util.getInstance() が呼び出されると問題が発生します。
明らかに、Util.getInstance() を呼び出すレガシー コードのすべてのクラスに新しいコンストラクタを追加することはできませんでした。
これが、「 Mockitoでwhen(Sth.getInstance()).thenReturn(myMock)
のようなものを使用できるかどうか」を尋ねている理由です 。
もう問題を起こさないでください。
うーん....何か考えはありますか?
****************************************************** *********************
解決策 : 私の場合の解決策はPowerMockだと思います