2016-08-03 17 views
0

DbContextをEF 6で擬似する明確な実例を示している多くの例が見つかりましたが、それらのどれも私にとってはうまくいかず、その理由が完全にわかりません。Entity Framework 6.1でDbContextをモックする

これはモックを設定する私のユニットテストコードです。

var mockData = new List<User> { new User { Email = "[email protected]", Id = 1 } }.AsQueryable(); 

var mockSet = new Mock<DbSet<User>>(); 
    mockSet.As<IQueryable<User>>().Setup(m => m.Provider).Returns(mockData.Provider); 
    mockSet.As<IQueryable<User>>().Setup(m => m.Expression).Returns(mockData.Expression); 
    mockSet.As<IQueryable<User>>().Setup(m => m.ElementType).Returns(mockData.ElementType); 
    mockSet.As<IQueryable<User>>().Setup(m => m.GetEnumerator()).Returns(mockData.GetEnumerator()); 

    var mockContext = new Mock<MyDbContext>(); 
    mockContext.Setup(c => c.Users).Returns(mockSet.Object); 

次に、私がテストしているサービスへの呼び出し。

var service = new UsersService(mockContext.Object); 

var user = service.GetById(1); 

これは、基になるDbSetが常にnullであるため、NullReferenceExceptionをスローします。コードは次のことを行います。

In BaseClass;

public IEnumerable<T> GetAll() 
{ 
    return _dbSet.AsEnumerable(); 
} 

サブクラスでは、

public User GetById(int id) 
     { 
      return GetAll().FirstOrDefault(x => x.Id == id); 
     } 

関連しているように見えるSO上の他の質問がありますが、彼らは参考のためEF 6

をカバーしていない、これはへの変更と同じコードというMSDNの記事であることに注意してくださいコンパイルしてください。

https://msdn.microsoft.com/en-us/data/dn314429.aspx

EDIT:

はUserServiceの(その用途ジェネリック/インターフェース)の複雑さを低減、コードは単に今あります。

public User GetById(int id) 
     { 
      return _dbContext.Set<User>().FirstOrDefault(x => x.Id == id); 
     } 

これをさらに変更すると、

var dbSet = _dbContext.Set<User>(); 
     return dbSet.FirstOrDefault(x => x.Id == id); 

明らかに、dbSetがnullであることがわかります。 wablabからの提案を1として

編集2

、モック.SETが問題を解決していることが表示されます。

DbSetの汎用メソッドについては、Vladyslav Kushnirにもクレジットされています。

これを必要とする人のためのコードです。ここで

private static Mock<DbSet<T>> GetDbSetMock<T>(IEnumerable<T> items = null) where T : class 
     { 
      if (items == null) 
      { 
       items = new T[0]; 
      } 

      var dbSetMock = new Mock<DbSet<T>>(); 
      var q = dbSetMock.As<IQueryable<T>>(); 

      q.Setup(x => x.GetEnumerator()).Returns(items.GetEnumerator); 

      return dbSetMock; 
     } 



var mockContext = new Mock<Model1>(); 

var users = new List<User> { new User { Email = "[email protected]", Id = 1 } }; 

mockContext.Setup(x => x.Set<User>()).Returns(GetDbSetMock(users).Object); 

var service = new UsersService(mockContext.Object); 

var user = service.GetById(1); 
+0

'UserService'コンストラクタが' _dbSet'フィールドに渡されたパラメータの 'Users'プロパティを割り当てていることを確認しましたか? – wablab

+0

それはあなたが意味するものであれば、ロックされていません。 – ChrisBint

+0

'GetById'メソッドまたは' GetAll'メソッドから 'NullReferenceException'がスローされていますか?つまり、 '_dbSet'はnullか、' _dbSet.AsEnumerable() 'nullの結果ですか? (または、何か他のnullですか?) – wablab

答えて

3

私はあなたのモックを返すためにSet<User>()方法でセットアップを作成する必要があると思います。

+0

完璧に作業しました。ありがとう – ChrisBint

0
private Mock<DbSet<T>> GetDbSetMock<T>(IEnumerable<T> items = null) where T : class 
    { 
     if (items == null) 
     { 
      items = new T[0]; 
     } 

     var dbSetMock = new Mock<DbSet<T>>(); 
     var q = dbSetMock.As<IQueryable<T>>(); 

     q.Setup(x => x.GetEnumerator()).Returns(items.GetEnumerator); 

     return dbSetMock; 
    } 

私はDbContextのDbSetをあざけるために使用しています私はかなりうまく機能し、一般的な方法です。この方法のactuall呼び出しは次のとおりです。

var contextMock = new Mock<MyContext>(); 
contextMock.Setup(x => x.MyDbEntities).Returns(GetDbSetMock<MyDbEntity>().Object); 
+0

奇妙なことに、それは私のマシンでは動作しません。dbsetはこのコードを使ってもnullです。 – ChrisBint

+0

また私の文脈の中では 'DbSet'の代わりに' IDbSet'を使っています。これを試してみてください。 –

+0

おそらく、このメソッドを追加して模擬しようとすると、 'Set 'でデータにアクセスしようとしているときに、DbContextの特定のプロパティを嘲笑しているので、このコードは機能しません。 –

関連する問題