しばやん雑記

Azure とメイドさんが大好きなフリーランスのプログラマーのブログ

Repository for ASP.NET MVC

ASP.NET MVC で Repository パターンを使う方法を少し調べたのでまとめてみる。

モデル

基本的な方針としては Repository のインターフェースを作って、そのインターフェースを実装したクラスを作る。何でインターフェースを用意するのかは、テスタビリティ向上の為。テストプロジェクトではそのインターフェースを実装したモッククラスを用意すればテストを簡単に出来る。

共通な部分は Generic 使ってさらにインターフェースとして切り出してやったほうがいいのかも。

public interface IRepository<T>
{
    void Add(T entity);
    void Remove(T entity);
    IList<T> ListAll();
}

public interface IBookmarkRepository : IRepository<Bookmark>
{
    Bookmark Find(string url);
}

// 実際に DB から引っ張ってくる Repository
public class BookmarkRepository : IBookmarkRepository
{
    // 実装は省略
}

// テスト用に使う偽 Repository
public class MockBookmarkRepository : IBookmarkRepository
{
    // 省略
}

モックの Repository はテストプロジェクトで実装するのが普通です。で Repository を作ったのはいいが、コントローラでどうやって使うかという話になるわけです。

コントローラ

DataContext や Entities はコントローラクラスのメンバとして用意して、定義と同時にインスタンス化するのが一般的かなと思います。でも定義と同時にインスタンス化するとテストプロジェクトからモックに入れ替えることが出来ないので、コンストラクタで Repository を指定できるようにします。

public class BookmarkController
{
    // MVC Framework からはこっちが呼ばれる
    public BookmarkController()
        : this(new BookmarkRepository())
    {
    }

    // テストプロジェクトからはこっちを呼び出す
    public BookmarkController(IBookmarkRepository repository)
    {
        _repository = repository;
    }

    private IBookmarkRepository _respository;
}

ASP.NET MVC は通常は引数無しのコンストラクタを呼び出すので、そっち側ではモックじゃない Repository をインスタンス化します。これでテストプロジェクトから自由に Repository を指定できるようになりました。