2016-09-14 3 views
3

Ich muss EF's DbContext Mock Mock. Ich benutze the approach here und es funktioniert gut.Wie mokiere ich DbContext mit NSubstitute und dann Hinzufügen/Entfernen von Daten

// 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); 

jedoch in einigen Tests benötigen ich in der Lage sein mockContext.Set<Foo>().Add(someFoo) und mockContext.Set<Foo>().Remove(otherFoo) zu nennen und für die zugrunde liegenden hinzufügen/entfernen Logik zu arbeiten.

Ich versuchte dies:

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

aber es wirft mit Collection was modified; enumeration operation may not execute.

So wie ich Additions-/Funktionalität entfernen?

+0

Ich muss zum Kontext hinzufügen/entfernen, nicht überprüfen, dass add/remove aufgerufen wurden (ich weiß, wie das geht). –

+0

Sie sollten den letzten Kommentar in Ihre ursprüngliche Frage als Bearbeitung einfügen, nicht als Kommentar, da nicht jeder die Kommentare liest. – Igor

+2

Ich habe vor kurzem begonnen, diese Hilfs-Bibliothek zu verwenden, und es scheint, dass es Hinzufügen/Entfernen unterstützt. Ich habe es für eine wie 10 Tests derzeit verwendet, so weiß ich nicht mehr https://github.com/scott-xu/EntityFramework.Testing – Stilgar

Antwort

2

Sie möchten es nicht zur Sammlung hinzufügen. Was Sie tun möchten, ist zu überprüfen, ob es (add/remove/etc) aufgerufen wurde und möglicherweise, wie es aufgerufen wurde.

// 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>()); 

Wenn Sie eine Foo zu einem späteren Zeitpunkt in Ihrem Test hinzufügen möchten Sie den Verweis auf die List von Foo ‚s halten.

// 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

Nein, ich * möchte den Kontext hinzufügen *. Ich kann das während der Initialisierung tun, aber manchmal muss ich das später tun. Bei einigen Tests ist es mir egal, ob sie angerufen wurden, aber ich brauche die Daten dort, damit ich sie für andere Zwecke verwenden kann. –

+0

@hbob - Das war mir nicht klar. Ich habe die Antwort aktualisiert. – Igor

+0

Ich habe das auch versucht, aber beim Zugriff auf das Mock-DbSet gibt es dieselbe Ausnahme - 'Collection wurde geändert; Aufzählungsoperation kann nicht ausgeführt werden. "(Was irgendwie Sinn macht, wenn Sie darüber nachdenken.) –

0

Der Kommentar von @Stilgar hat mich der Blick in EntityFramework.Testing Bibliothek, die this very problem löst.

Also habe ich meine Sachen mit dieser Bibliothek ersetzt (eine Sache weniger, um die ich mich kümmern muss).

Verwandte Themen