委譲のユニットテスト

こんな感じのクラスとメソッドがあるとする。

public class Model() implements Editor, Writer {
  @Override
  public edit() {
  //Editorの実装
  }

  @Override
  public write() {
  //Writerの実装
  }
}
public class Facade() {
  private Editor editor;
  private Writer writer;

    public Facade(Model model) {
      this.editor = model;
      this.writer = model;
    }

    public Edit() {
      editor.edit();
    }

    public Write() {
      writer.write();
    }
}

意図としては、こんな役割分担。

  • Facadeクラスの役割は、あくまで「Modelに処理をさせる」という内容
  • 実際の編集はModelクラスが行う

さて、こんな時Facade.Editのテストをどうしよう。

  • Modelクラス→Facadeクラスと作ってテストする。検証はModelを比較することで行う。

ってしたいけどこれだと「Facadeは依頼するだけ」という立場であることを検証できていない気がする。それにこの検証はModelクラスのEditメソッドのテストと同じことをする破目になりそう。EditorやWriterのダミー的なものを使えるようにしてそれで検証するのがいいのかな?

          • 2015/08/19追記

結局、テスト実行クラスの内部クラスとしてModelを継承して、メソッドをオーバーライドするテストコードにしてみた。テスト対象メソッドがオーバーライドされたものを起動することで委譲を確認するって感じ。classがfinal修飾されてる場合は考えないことにしよう。

 @Test
 public testEdit() {
   public class TestingModel extends Model {

    @Override
    public Edit() {
      System.out.println("テスト用メソッド");
    }
  }
  TestingModel model = new TestingModel();
  Facade fcade = facade(model);
  facade.edit();
}

テスト対象クラスの設計を見直したほうがいいというのはもっともだけどそっちは諦めた。

他に考えたアイディアは、

  1. リフレクションでオブジェクトを弄ってしまう
  2. テスト対象クラスにテスト専用機能を作る
  3. テスト対象クラスのフィールドのアクセス修飾子を弄る

それぞれ次のような理由で却下。

  1. 使い方分からない
  2. わざわざそれを作るのも何か違う気がするっていうのと、他の場所での制限する手が分からない
  3. 元の機能を変更するのはどうかと思う

テスト対象にテスト用の機能を作るのはありかなと思う。適切に量を制限できるなら。テスト側からだけ使えるよってのは専用のアノテーション作ってで表現するとかかな。ただ、コレって実質的に裏口を作るようなものだしどうなんだろうなぁ……。