レガシ―コード改善ガイド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(...){} }