2016-09-14 13 views
3

EFのDbContextをモックする必要があります。私はthe approach hereを使用し、うまく動作します。NSubstituteを使用してDbContextをモックし、データを追加/削除する方法

// mock a DbSet 
var mockDbSet = Substitute.For<DbSet<Foo>, IQueryable<Foo>>(); 
var data = new List<Foo>().AsQueryable(); 
((IQueryable<Foo>)mockDbSet).Provider.Returns(data.Provider); 
((IQueryable<Foo>)mockDbSet).Expression.Returns(data.Expression); 
((IQueryable<Foo>)mockDbSet).ElementType.Returns(data.ElementType); 
((IQueryable<Foo>)mockDbSet).GetEnumerator().Returns(data.GetEnumerator()); 
// now add it to a mock DbContext 
var mockContext = Substitute.For<MyDbContextClass>(); 
mockContext.Set<Foo>().Returns(mockDbSet); 

は、しかし、いくつかのテストでは、私はmockContext.Set<Foo>().Add(someFoo)mockContext.Set<Foo>().Remove(otherFoo)、および基礎となる追加/削除するロジックが機能するために呼び出すことができるようにする必要があります。

私はこの試みた:

mockDbSet.When(x => x.Add(Arg.Any<Foo>())).Do(x => data.Add(x.Arg<Foo>())); 

を、それは、どのように私は機能を追加/削除実装するのですCollection was modified; enumeration operation may not execute.

とスロー?

+0

追加/削除が呼び出されたことを確認するのではなく、コンテキストに追加/削除する必要があります(これを行う方法はわかります)。 –

+0

元の質問に最後のコメントを編集として含めてください。誰もコメントを読んでいないので、コメントとしてコメントする必要はありません。 – Igor

+2

最近、このヘルパーライブラリを使用し始めました。追加/削除をサポートしているようです。私は今のような10のテストのためにそれを使用していますので、私はもっと知りませんhttps://github.com/scott-xu/EntityFramework.Testing – Stilgar

答えて

2

コレクションに追加したくない場合。あなたがしたいのは、それが(追加/削除/ etc)が呼び出されたのか、おそらくそれが呼び出されたのかをチェックすることです。

// arrange - check what it was called with. You place asserts in the body of the `Do` expression. Place this before your call that actually executes the code 
mockDbSet.Add(Arg.Do<Foo>(foo => 
{ 
    Assert.IsNotNull(foo); 
    // Assert other properties of foo 
})); 

// act 


// assert. Make sure that it was actually called 
mockDbSet.Received(1).Add(Arg.Any<Foo>()); 

、あなたのテストの後の時点でFooを追加したい場合は、ListFooの年代への参照を保持することができます。

// mock a DbSet 
var mockDbSet = Substitute.For<DbSet<Foo>, IQueryable<Foo>>(); 
var fooList = new List<Foo>(); 
var data = fooList.AsQueryable(); 
// rest of your code unchanged 

// add it from the code being tested through the mock dbset 
mockDbSet.Add(Arg.Do<Foo>(foo => 
{ 
    fooList.Add(foo); 
    // at this point you have to recreate the added IQueryable 
    data = fooList.AsQueryable(); 
    // rest of code you had to add this to the mockDbSet 
})); 


// act 
+0

いいえ*私は*文脈に追加したいです。私はそれを初期化中に行うことができますが、時にはあとで行う必要があります。いくつかのテストでは、呼び出されたかどうかは気にしませんが、そこにデータが必要なので、他の目的で使うことができます。 –

+0

@hbob - それは私には分かりませんでした。私は答えを更新しました。 – Igor

+0

私もそれを試みましたが、模擬DbSetにアクセスすると、同じ例外がスローされます。列挙操作が実行されない可能性があります。(あなたがそれについて考えるときにはちょっと意味があります) –

0

@Stilgarによってコメントは私がthis very problemを解決EntityFramework.Testingライブラリー、に見せていました。

私はこのライブラリと私のものを置き換えました(心配することは1つ少ない)。

関連する問題