レガシ―コード改善ガイド4

このクラスをテストハーネスに入れることができません

いらただしいパラメータ

本番コードでは、それ以外に手段がない場合を除き、パラメーターにnullを渡すのはやめる。
nullを渡せるような実装だと、処理の至る所でパラメーターチェック処理が行われているはず。これはまずい。(可読性の問題)
代わりにNullオブジェクトパターンの適用を検討すべし。テストケースではnullを渡してもOK。

いらだたしいグローバルな依存関係

Singletonなクラスを内部で使用しているクラスに対するテスト。
→"Singletonなクラスの制約を緩和する" という発想があまり理解できない。
テスト用の処置ならわかるが、本番でもグローバル変数としてSingletonクラスを使用するのもOK!と書かれているように思える。
グローバルな変数を使用したい→Singletonクラスを作成!という判断に自分がどうしてもならないからか?

紹介されていることをソースに落とすとこんな感じでしょうか?

//シングルトンクラスのインターフェイス
public interface ISingleton
{
  int GetHogegeInt();
  ...
}

//シングルトンクラス
public class HogeSingleton : ISingleton
{
  private static ISingleton instance = null;

  protected HogeSingleton(){}

  //言語によっては、アクセス制限をかけることができる。("テストクラスのアセンブリからのみアクセス可"みたいな感じ)
  public static void SetTestingInstance(ISingleton newInstance)
  {
    instance = newInstance;
  }

  public static ISingleton getInstance()
  {
    if(instance == null){
      instance = new HogeSingleton();
    return instance;
  }

  public int GetHogegeInt()
  {
    ...
  }

  ....

}

//テスト用のシングルトンクラス
public SingletonForTest : ISingleton
{
    public SingletonForTest()
    {
      ...
    }

    public int GetHogegeInt()
    {
      ...
    }

    ...
}

//内部でシングルトンクラスオブジェクトを使用しているクラス
public class UseSingletonProc
{
    public UseSingletonProc()
    {
      int hogeInt = HogeSingleton.GetInstance().GetHogegeInt();
      ...
    }

    public bool ExistValue()
    {
      ...
    }

    ....
}

//テストクラス
public class ATestClass
{
  ...

  //テストケース
  public void TestCase()
  {
    HogeSingleton.SetTestingInstance(new SingletonForTest());
    
    var obj = new UseSingletonProc();
    Assert.AreEqure(true, obj.ExistValue());

    ...
  }

  ...
}


*追記
「いらだたしいグローバルな依存関係」の対応例について、自分なら下のような対応を行う。
「staticなクラスが何かのインターフェイスを実装する」というのを見たことが無いので、落ち着かない。

interface IHogege{ ... }
class Hogege : IHogege {...}
class TestingHogege : IHogege{...}

class HogegeFactory
{
   private static HogegeFactory instance;
   public static HogegeFactory CreateInstance(){ ...}
   public void SetHogegeType(Type hogegeType){...}
   public IHogege Create(...){}
}