0

linqtosqlコードを含むクラスの単体テストを作成したいと思います。つまり、各メソッド内で、新しいDbContextを作成し、データベースジョブを実行しました。

ウェブを検索しました。最初にリポジトリと作業ユニットのパターンを使用するようになりましたが、DbContext自体が作業ユニットであり、そのdbsetがリポジトリとして機能することがわかりました。もう1つのポイントは、Linqパーツは正常に機能するため、テストする必要はないと思います(.netチームによるテスト)。コードに追加したロジックをテストしたいと思います。そこで、2つの実装で必要なメソッドを使用してインターフェイスを作成することにしました。1つはlinqToSqlを使用し、もう1つは単なるモックです。このようなもの :

    public interface IDbManager
    {
        bool Insert(MyEntity newEntity);
    }

    public class RealDbManager:IDbManager
    {
        public bool Insert(MyEntity newEntity)
        {
            using (DbDataContext db = new DbDataContext())
            {
                db.MyEntities.InsertOnSubmit(newEntity);
                db.SubmitChanges();
            }
        }
    }

    public class MockDbManager:IDbManager
    {
        public bool Insert(MyEntity newEntity)
        {
            return true;
        }
    }

アイデア全体は正しいですか?もしそうなら、これは正しい実装ですか?

各メソッド内に新しいインスタンスを作成する代わりに、DbDataContextをクラス変数として定義することは可能ですか?

4

2 に答える 2

1

あなたは最初に正しい一般的な考えを持っています。MockInsertメソッドは、エンティティをメモリ内ストアに保存して、後続のクエリが挿入された情報を期待どおりに返すようにする必要があります。しかし、「本物の」実装と「モック」の実装を備えたインターフェースを持つという非常に基本的な考え方はそこにあります。

テストでモックを使用するときは、モック自体ではなく、モックを使用する他のコードをテストしていることに注意してください。

DataContext をメンバー変数として定義する場合と同様です。次のように IDisposable パターンを使用できます。

public class RealDbManager:IDbManager, IDisposable
{
    DbDataContext db = new DbDataContext();
    public bool Insert(MyEntity newEntity)
    {
        {
            db.MyEntities.InsertOnSubmit(newEntity);
            db.SubmitChanges();
        }
    }
    public void Dispose()
    {
        db.Dispose();
    }
}

その場合は、必ず DbManager を破棄する必要があります。

于 2012-09-05T09:50:58.233 に答える
1

はい。私が避ける唯一のことは、実際のモック クラス (この場合は Fake と呼ばれる必要があります) を作成することですが、モック エンジンを使用します。

あなたの質問では、2種類のテストについて言及しています。1 つ目はクラスの動作をテストすることで、2 つ目はクラスの統合をテストすることです。それらは同じように見えますが、そうではありません。

最初に、この方法で (Moq を使用して) 他のクラスとの「接続」をテストするために、クラスをモックする必要があります。

  [Test]
  public void Test()
  {
       var entity = new Entity();
       var mocked = new Mock<IDbManager>();
       //you are telling the moq engine everytimes it finds an invocation of your repository
       //to return true as you did in you mocked class
       mocked.Setup( x => x.Insert( entity ) ).Returns( true );

       var classUnderTest = new ClassUnderTest( mocked.Object );
       //in this method you invoke your repository
       var ret = classUnderTest.DoSomething( entity );

       //assertions
       Assert.Equal( something, ret);

      //eventually you can verify that your repository has been hit once
      mocked.Verify( x => x.Insert( It.IsAny<Entity>), Times.Once);
  }

後で正しく述べたように、linqでテストすることは何もありません(Microsoftが私たちのためにそれを行いました)が、linqの正確性を検証する必要がある場合は、実際のデータベースに対してのみ(またはリポジトリパターンを使用して)行うことができます偽のリポジトリに対して)。これは統合テストであり、モックと共有するものは何もありません。

クラスを DbContext から切り離すには、リポジトリ パターンを使用できます。この記事を見てください。http://dotnetspeak.com/index.php/2011/03/repository-pattern-with-entity-framework/

于 2012-09-05T10:07:34.713 に答える