2017-05-20 9 views
0

私はMoqを使い始めました。私はそれを使って単体テストを書いています。これは私がモックとしたいlocaldb、上のデータベースであるC#/ Moq - マルチレベルのテストデータをどのように埋めるのですか?

EducationUser | Application 
- UsrName   - Student 
- UsrPwd   - CourseId 
- UsrChallenge - Date 
- IsTeacher  - Grade 
- FullName 

:ように私は、いくつかのテーブルを持つデータベースを持っています。 Entity Frameworkを使用してエンティティを作成しました。これらのエンティティのインターフェイスはIEducationEntitiesです。今

私はのように、いくつかのWebサービスのいくつかのテストをモックオブジェクトを作成してくださいしたい:私はdocumentationから理解してきたこと、私のことができるようにすべきであるから、このために

[TestMethod()] 
    public void LoginTest() 
    { 
     HttpResponseMessage response = Request.CreateResponse(_accountController.Login("andrew", "DefaultPassword")); 
     Assert.IsTrue(response.IsSuccessStatusCode, "User unable to log in with correct login info"); 

    } 

:databseから生成された実体が明らかにサブフィールドの情報が含まれていない、と私はエラーを取得するので、これは、まったく動作しない

[TestClass()] 
public class AccountControllerTests : ApiController 
{ 
    Mock<IEducationEntities> _entities = new Mock<IEducationEntities>(MockBehavior.Strict); 
    private AccountController _accountController; 

public AccountControllerTests() { 
     _accountController = new AccountController(_entities.Object); 
     _entities.Setup(table => table.EducationUsers.UsrName).Returns("andrew"); 
     _entities.Setup(table => table.EducationUsers.UsrPwd).Returns("DefaultPassword"); 
} 
[TestMethod] //etc, defining tests below 

:ような何かを行います3210

'DbSet' does not contain a definition for 'UsrPwd' and no extension method 'UsrPwd' accepting a first argument of type 'DbSet' could be found (are you missing a using directive or an assembly reference?)

私は何が欠けていますか?私のデータベースと同じ構造を持つテストデータでmoqオブジェクトを埋める方法は?それはおそらく、すべてのエンティティタイプのためDbSetモックを設定する迷惑取得します

[TestMethod] 
public void TestSomething()  
{ 
    // Create the user data 
    var educationUsers = new List<EducationUser> 
    { 
     new EducationUser 
     { 
      UsrName = "andrew", 
      UsrPwd = "DefaultPassword" 
     } 
    }.AsQueryable(); 

    // Create the DbSet that contains the user data and wire it up to return the user data that was created above 
    Mock<DbSet<EducationUser>> educationUsersDbSet = new Mock<DbSet<EducationUser>>(); 
    educationUsersDbSet.As<IQueryable<EducationUser>>().Setup(m => m.Provider).Returns(educationUsers.Provider); 
    educationUsersDbSet.As<IQueryable<EducationUser>>().Setup(m => m.Expression).Returns(educationUsers.Expression); 
    educationUsersDbSet.As<IQueryable<EducationUser>>().Setup(m => m.ElementType).Returns(educationUsers.ElementType); 
    educationUsersDbSet.As<IQueryable<EducationUser>>().Setup(m => m.GetEnumerator()).Returns(educationUsers.GetEnumerator()); 

    // Create the mock context and wire up its EducationUsers property to return the DbSet that was created above 
    var context = new Mock<IEducationEntities>(); 
    context.Setup(e => e.EducationUsers).Returns(educationUsersDbSet.Object); 

    // Create the account controller using the mock DbContext 
    _accountController = new AccountController(context.Object); 

    // ... the rest of your testing code ... 
} 

+0

なり、パスワードフィールドが 'UsrPassword'と呼ばれていますが、テスト/モックコードで' UsrPwd'それを呼び出します。 –

答えて

2

This article describes how to mock your Entity Framework context

あなたはこのような何かをやります(あなたはバージョン6以降を使用していると仮定)すべてのユニットテストのために、あなたはそれを行う方法を作ることができます。

public static Mock<DbSet<TEntity>> CreateMockDbSet<TEntity>(IQueryable<TEntity> models) where TEntity : class 
{ 
    Mock<DbSet<TEntity>> dbSet = new Mock<DbSet<TEntity>>(); 

    dbSet.As<IQueryable<TEntity>>().Setup(e => e.ElementType).Returns(models.ElementType); 
    dbSet.As<IQueryable<TEntity>>().Setup(e => e.Expression).Returns(models.Expression); 
    dbSet.As<IQueryable<TEntity>>().Setup(e => e.GetEnumerator()).Returns(models.GetEnumerator()); 
    dbSet.As<IQueryable<TEntity>>().Setup(e => e.Provider).Returns(models.Provider); 

    return dbSet; 
} 

次に、あなたの試験方法はあなたの例のテーブル構造で

[TestMethod] 
public void TestSomething()  
{ 
    // Create the user data 
    var educationUsers = new List<EducationUser> 
    { 
     new EducationUser 
     { 
      UsrName = "andrew", 
      UsrPwd = "DefaultPassword" 
     } 
    }.AsQueryable(); 

    // Create the DbSet that contains the user data and wire it up to return the user data that was created above 
    Mock<DbSet<EducationUser>> educationUsersDbSet = new CreateMockDbSet(educationUsers); 

    // Create the mock context and wire up its EducationUsers property to return the DbSet that was created above 
    var context = new Mock<IEducationEntities>(); 
    context.Setup(e => e.EducationUsers).Returns(educationUsersDbSet.Object); 

    // Create the account controller using the mock DbContext 
    _accountController = new AccountController(context.Object); 

    // ... the rest of your testing code ... 
} 
+0

私はasync/awaitパターンの実装を開始するまで、上記のアプローチをとっていました。あなたが提供されたリンクを読むなら、このアプローチはそれについてはうまくいかないと説明しています。また、それらがasync/awaitに提供するアプローチはEFコアでは機能しないため、注意してください。私はEFコアのUseInMemoryDatabaseを使用して、ユニットテストを行って、リポジトリレイヤーまで成功させました。あなたが例に興味があるなら、私はそれを提供します。 – MORCHARD

+1

はい、私は例を見てみたいと思います。 –

関連する問題