Help us understand the problem. What is going on with this article?

ASP.NET MVCのユニットテストを実装するときに考えたこと

More than 3 years have passed since last update.

ASP.NET MVCでテストを書く際に考えたことのメモ

おすすめのパッケージ

Moq

テストのためのダミーオブジェクトを作成するパッケージ。

簡単な使い方

var mock = new Mock<IHelloModel>();
mock.Setup(x => x.Hello()).Returns("test return");

IHelloModel hello = mock.object;

ChainingAssertion

MsTestも手軽にいい感じにかけるパッケージ。

test = "test";
test.Is<string>("test"); // 成功

コントローラのテスト

とりあえず、コントローラのテストを書いてみた。

public class HelloControllerTest
{
    [TestClass] /* テスト対象群であることを表す */
    public class Index /* テストしたいメソッド名 */
    {
        private HogeController controller;

        [TestInitialize] /* テストの初期化処理毎。テスト毎に実行される */
        public void TestInitialize()
        {
            // コントローラを初期化
            this.controller = new HogeController();

            // Indexアクションを実行する
            var result = await this.controller.Index() as ActionResult;
        }

        [TestMethod] /* テスト対象 */
        public async Task 一覧画面が表示されること()
        {
            // 結果オブジェクトがどうなっているかを確認する
            result.IsInstanceOf<HogeResult>();
        }
    }
}

テストしやすいコード

とにかく DI (Dependency Injectyon) する

class HogeController
{
  private IDependencyClass _Fuga { get; set; }

  // 引数がないときは新しいインスタンスを注入する
  public HogeController() : this(new DependencyClass()) { }
  public HogeController(IDependencyClass fuga)
  {
    this._Fuga = fuga;
  }
}

そうするとモックテストがはかどる

...
// Helloメソッドが"hello"を返すモックを作る
var mock = new Mock<IDependencyClass>();
mock.Setup(x => x.Hello()).Returns("hello");

// 作ったモックを注入したコントローラーをテストできる
var controller = new HogeController(mock.object);
var result = controller.Index() as ActionResult;
...

意識したいこと

  • DI
    • メソッドが利用しているクラスと結合しすぎてしまうため、インスタンスの生成処理は極力内部で行わない
    • 他クラスを参照する場合は、DIで利用することを意識する
    • DIモジュールをインタフェースで定義する
  • 単一責任
    • 一つのメソッドに色々な処理を含めず(ifでの分岐を減らす)、責任を一つにしてメソッドを分ける
    • メソッド名と処理内容が一致しやすく読みやすくなる
  • 担当の明確化
    • Sessionやリクエストの状態はControllerに任せる(Model側に意識させない)
    • ModelはDBと切り離しなるべくプレーンなクラスにする(POCO)。DBを意識させない
    • Repositoryパターンを使うといい?かも
    • ViewModelは表示に関する処理のみ記述する。値の生成などはModel側でやりたい
  • Ruby on Rails的な思想
    • DRY (Don't repeat yourself)
    • 同じ処理は2度書かない
    • レールに乗る (ベストプラクティスから外れないようにつくる)
    • 他の人が読みやすいコードになる
    • Rails程レールはないが、規約決めるといいかも
  • 個人的な見解
    • 性能より保守性
    • LINQやEntityFrameworkを積極的に使いたい
    • コードファースト
    • Dbの構造のコード化
      • DRYにもつながる
    • 自動テストの利点
      • 変更に強くなる
      • コードが読みやすくなる

その他

MSTestを全く触ったことがないので、他にもいいパッケージなど教えてほしいです...

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away